From 3f36b4c1dd9a3c57457b3e829ca363f49b968a00 Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Thu, 3 Feb 2022 02:00:09 +0000 Subject: [PATCH 01/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 482 ++++++++++++++++++------------------ 1 file changed, 241 insertions(+), 241 deletions(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 1c5d5b4e9..36262022b 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -73,7 +73,7 @@ "admin.dashcounters.user_count_label": "סך כל המשתמשים", "admin.dashwidgets.email_list_header": "רשימת דואר", "admin.dashwidgets.software_header": "תוכנה", - "admin.latest_accounts_panel.expand_message": "לחץ כדי לראות {count} עוד{count, plural, one {account} אחר {accounts}}", + "admin.latest_accounts_panel.expand_message": "לחץ כדי לראות {count} עוד{count, plural, one {account} other {accounts}}", "admin.latest_accounts_panel.title": "חשבונות אחרונים", "admin.moderation_log.empty_message": "לא ביצעת פעולות ניהול עדיין. כשתבצע, ההיסטוריה תהיה כאן.", "admin.reports.actions.close": "סגור", @@ -109,11 +109,11 @@ "admin.users.user_unsuggested_message": "@{acct} was unsuggested", "admin.users.user_unverified_message": "@{acct} was unverified", "admin.users.user_verified_message": "@{acct} was verified", - "admin_nav.awaiting_approval": "Awaiting Approval", - "admin_nav.dashboard": "Dashboard", - "admin_nav.reports": "Reports", + "admin_nav.awaiting_approval": "מחכה לאישור", + "admin_nav.dashboard": "לוח מחוונים", + "admin_nav.reports": "דיווחים", "alert.unexpected.clear_cookies": "נקה קובצי 'עוגיות' ונתוני דפדפן", - "alert.unexpected.help_text": "If the problem persists, please notify a site admin with a screenshot and information about your web browser. You may also {clear_cookies} (this will log you out).", + "alert.unexpected.help_text": "אם הבעיה נמשכת, אנא הודע למנהל האתר עם צילום מסך ומידע על דפדפן האינטרנט שלך. אתה יכול גם {clear_cookies} (זה יוציא אותך מהחשבון).", "alert.unexpected.message": "אירעה שגיאה בלתי צפויה.", "alert.unexpected.return_home": "חזור הביתה", "alert.unexpected.title": "אופס!", @@ -128,47 +128,47 @@ "app_create.redirect_uri_label": "נתב URIs", "app_create.restart": "צור עוד", "app_create.results.app_label": "אפליקציה", - "app_create.results.explanation_text": "You created a new app and token! Please copy the credentials somewhere; you will not see them again after navigating away from this page.", - "app_create.results.explanation_title": "App created successfully", - "app_create.results.token_label": "OAuth token", - "app_create.scopes_label": "Scopes", - "app_create.scopes_placeholder": "e.g. 'read write follow'", - "app_create.submit": "Create app", - "app_create.website_label": "Website", - "auth.invalid_credentials": "Wrong username or סיסמא", - "auth.logged_out": "Logged out.", - "backups.actions.create": "Create backup", - "backups.empty_message": "No backups found. {action}", - "backups.empty_message.action": "Create one now?", - "backups.pending": "Pending", + "app_create.results.explanation_text": "יצרת אפליקציה ואסימון חדשים! אנא העתק את האישורים למקום כלשהו; לא תראה אותם שוב לאחר ניווט מדף זה.", + "app_create.results.explanation_title": "האפליקציה נוצרה בהצלחה", + "app_create.results.token_label": "אסימון OAuth", + "app_create.scopes_label": "היקפים", + "app_create.scopes_placeholder": "למשל 'קרא כתוב עקוב'", + "app_create.submit": "צור אפליקציה", + "app_create.website_label": "אתר", + "auth.invalid_credentials": "שם משתמש או סיסמא שגוי", + "auth.logged_out": "מנותק", + "backups.actions.create": "צור גיבוי", + "backups.empty_message": "לא נמצאו גיבויים. {action}", + "backups.empty_message.action": "האם ליצור אחד עכשיו?", + "backups.pending": "בהמתנה", "boost_modal.combo": "ניתן להקיש {combo} כדי לדלג בפעם הבאה", "bundle_column_error.body": "משהו השתבש בעת הצגת הרכיב הזה.", "bundle_column_error.retry": "לנסות שוב", - "bundle_column_error.title": "Network error", + "bundle_column_error.title": "תקלת רשת", "bundle_modal_error.close": "לסגור", "bundle_modal_error.message": "משהו השתבש בעת טעינת הרכיב הזה.", "bundle_modal_error.retry": "לנסות שוב", - "chat_box.actions.close": "Close chat", - "chat_box.actions.send": "Send", - "chat_box.input.placeholder": "Send a message…", - "chat_panels.main_window.empty": "No chats found. To start a chat, visit a user's profile.", - "chat_panels.main_window.title": "Chats", - "chats.actions.delete": "Delete message", - "chats.actions.more": "More", - "chats.actions.report": "Report user", - "chats.attachment": "Attachment", - "chats.attachment_image": "Image", - "chats.audio_toggle_off": "Audio notification off", - "chats.audio_toggle_on": "Audio notification on", + "chat_box.actions.close": "סגור צ'אט", + "chat_box.actions.send": "שליחה", + "chat_box.input.placeholder": "שלח הודעה", + "chat_panels.main_window.empty": "לא נמצאו צ'אטים. כדי להתחיל צ'אט, בקר בפרופיל של משתמש.", + "chat_panels.main_window.title": "צ'אטים", + "chats.actions.delete": "מחק הודעה", + "chats.actions.more": "עוד", + "chats.actions.report": "דווח על משתמש", + "chats.attachment": "צירוף", + "chats.attachment_image": "תמונה", + "chats.audio_toggle_off": "התראת שמע כבויה", + "chats.audio_toggle_on": "התראת שמע דלוקה", "chats.dividers.today": "היום", "chats.search_placeholder": "התחל בצ'אט עם", - "column.admin.awaiting_approval": "Awaiting Approval", - "column.admin.dashboard": "Dashboard", - "column.admin.moderation_log": "Moderation Log", - "column.admin.reports": "Reports", - "column.admin.reports.menu.moderation_log": "Moderation Log", - "column.admin.users": "Users", - "column.aliases": "Account aliases", + "column.admin.awaiting_approval": "מחכה לאישור", + "column.admin.dashboard": "לוח מחוונים", + "column.admin.moderation_log": "יומן ניהול", + "column.admin.reports": "דיווחים", + "column.admin.reports.menu.moderation_log": "יומן ניהול", + "column.admin.users": "משתמשים", + "column.aliases": "כינויים בחשבון", "column.aliases.create_error": "שגיאה ביצירת כינוי", "column.aliases.delete": "מחק כינוי", "column.aliases.delete_error": "שגיאה במחיקת כינוי", @@ -228,133 +228,133 @@ "column.preferences": "העדפות", "column.profile_directory": "מדריך פרופילים", "column.public": "בפרהסיה", - "column.reactions": "Reactions", - "column.reblogs": "Reposts", - "column.remote": "Federated timeline", - "column.scheduled_statuses": "Scheduled Posts", - "column.search": "Search", - "column.security": "Security", - "column.soapbox_config": "Soapbox config", + "column.reactions": "תגובות", + "column.reblogs": "הדהודים", + "column.remote": "ציר זמן פדרטיבי", + "column.scheduled_statuses": "פוסטים מתוזמנים", + "column.search": "חפש", + "column.security": "אבטחה", + "column.soapbox_config": "תצורות סבוניה", "column_back_button.label": "חזרה", - "column_forbidden.body": "You do not have permission to access this page.", + "column_forbidden.body": "אין לך הרשאה לגשת לדף זה.", "column_forbidden.title": "אסור", "column_header.hide_settings": "הסתרת העדפות", "column_header.show_settings": "הצגת העדפות", "community.column_settings.media_only": "רק מדיה", - "community.column_settings.title": "Local timeline settings", - "compose.character_counter.title": "Used {chars} out of {maxChars} characters", - "compose.invalid_schedule": "You must schedule a post at least 5 minutes out.", - "compose.submit_success": "Your post was sent", - "compose_form.direct_message_warning": "This toot will only be visible to all the mentioned users.", - "compose_form.hashtag_warning": "This post won't be listed under any hashtag as it is unlisted. Only public posts can be searched by hashtag.", + "community.column_settings.title": "הגדרות ציר זמן מקומי", + "compose.character_counter.title": "השתמת ב{chars} מתוך {maxChars} תווים", + "compose.invalid_schedule": "עליך לתזמן פוסט לפחות 5 דקות.", + "compose.submit_success": "הפוסט שלך נשלח", + "compose_form.direct_message_warning": "פוסט זה יהיה גלוי רק לכל המשתמשים שהוזכרו.", + "compose_form.hashtag_warning": "פוסט זה לא יופיע תחת שום האשטאג מכיוון שהוא לא רשום. ניתן לחפש רק פוסטים ציבוריים לפי האשטאג.", "compose_form.lock_disclaimer": "חשבונך אינו {locked}. כל אחד יוכל לעקוב אחריך כדי לקרוא את הודעותיך המיועדות לעוקבים בלבד.", "compose_form.lock_disclaimer.lock": "נעול", - "compose_form.markdown.marked": "Post markdown enabled", - "compose_form.markdown.unmarked": "Post markdown disabled", - "compose_form.message": "Message", - "compose_form.placeholder": "מה עובר לך בראש?", - "compose_form.poll.add_option": "Add a choice", - "compose_form.poll.duration": "Poll duration", - "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", - "compose_form.poll.switch_to_multiple": "Change poll to allow multiple choices", - "compose_form.poll.switch_to_single": "Change poll to allow for a single choice", + "compose_form.markdown.marked": "סימון פוסט למארקדאון מופעל", + "compose_form.markdown.unmarked": "סימון פוסט למארקדאון מושבת", + "compose_form.message": "הודעה", + "compose_form.placeholder": "נחתתי בלוס אנג'לס", + "compose_form.poll.add_option": "הוסף בחירה", + "compose_form.poll.duration": "משך הסקר", + "compose_form.poll.option_placeholder": "בחירה {number}", + "compose_form.poll.remove_option": "הסר את הבחירה הזו", + "compose_form.poll.switch_to_multiple": "שנה סקר כדי לאפשר אפשרויות בחירה מרובות", + "compose_form.poll.switch_to_single": "שנה סקר כדי לאפשר בחירה יחידה", "compose_form.publish": "ללחוש", "compose_form.publish_loud": "לחצרץ!", - "compose_form.schedule": "Schedule", - "compose_form.scheduled_statuses.click_here": "Click here", - "compose_form.scheduled_statuses.message": "You have scheduled posts. {click_here} to see them.", - "compose_form.sensitive.hide": "Mark media as sensitive", - "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.schedule": "לתזמן", + "compose_form.scheduled_statuses.click_here": "לחץ כאן", + "compose_form.scheduled_statuses.message": "יש לך פוסטים מתוזמנים. {לחץ_כאן} כדי לראות אותם.", + "compose_form.sensitive.hide": "סמן מדיה כרגישה", + "compose_form.sensitive.marked": "מדיה מסומנת כרגישה", + "compose_form.sensitive.unmarked": "מדיה לא מסומנת כרגישה", + "compose_form.spoiler.marked": "טקסט מוסתר מאחורי אזהרה", + "compose_form.spoiler.unmarked": "הטקסט אינו מוסתר", "compose_form.spoiler_placeholder": "אזהרת תוכן", "confirmation_modal.cancel": "ביטול", - "confirmations.admin.deactivate_user.confirm": "Deactivate @{name}", - "confirmations.admin.deactivate_user.message": "You are about to deactivate @{acct}. Deactivating a user is a reversible action.", - "confirmations.admin.delete_local_user.checkbox": "I understand that I am about to delete a local user.", - "confirmations.admin.delete_status.confirm": "Delete post", - "confirmations.admin.delete_status.message": "You are about to delete a post by @{acct}. This action cannot be undone.", - "confirmations.admin.delete_user.confirm": "Delete @{name}", - "confirmations.admin.delete_user.message": "You are about to delete @{acct}. THIS IS A DESTRUCTIVE ACTION THAT CANNOT BE UNDONE.", - "confirmations.admin.mark_status_not_sensitive.confirm": "Mark post not sensitive", - "confirmations.admin.mark_status_not_sensitive.message": "You are about to mark a post by @{acct} not sensitive.", - "confirmations.admin.mark_status_sensitive.confirm": "Mark post sensitive", - "confirmations.admin.mark_status_sensitive.message": "You are about to mark a post by @{acct} sensitive.", - "confirmations.admin.reject_user.confirm": "Reject @{name}", - "confirmations.admin.reject_user.message": "You are about to reject @{acct} registration request. This action cannot be undone.", - "confirmations.block.block_and_report": "Block & Report", + "confirmations.admin.deactivate_user.confirm": "השבת @{name}", + "confirmations.admin.deactivate_user.message": "אתה עומד להשבית את @{acct}. השבתת משתמש היא פעולה הפיכה.", + "confirmations.admin.delete_local_user.checkbox": "אני מבין שאני עומד למחוק משתמש מקומי.", + "confirmations.admin.delete_status.confirm": "מחק פוסט", + "confirmations.admin.delete_status.message": "אתה עומד למחוק פוסט מאת @{acct}. לא ניתן לבטל פעולה זו.", + "confirmations.admin.delete_user.confirm": "מחק @{name}", + "confirmations.admin.delete_user.message": "אתה עומד למחוק את @{acct}. זוהי פעולה הרסנית שלא ניתן לבטלה!!!", + "confirmations.admin.mark_status_not_sensitive.confirm": "סמן שהפוסט לא רגיש", + "confirmations.admin.mark_status_not_sensitive.message": "אתה עומד לסמן שפוסט מאת @{acct} אינו רגיש.", + "confirmations.admin.mark_status_sensitive.confirm": "סמן את הפוסט כרגיש", + "confirmations.admin.mark_status_sensitive.message": "אתה עומד לסמן פוסט של @{acct} רגיש.", + "confirmations.admin.reject_user.confirm": "דחה @{name}", + "confirmations.admin.reject_user.message": "אתה עומד לדחות את בקשת הרישום @{acct}. לא ניתן לבטל פעולה זו.", + "confirmations.block.block_and_report": "חסום ודווח", "confirmations.block.confirm": "לחסום", "confirmations.block.message": "לחסום את {name}?", "confirmations.delete.confirm": "למחוק", - "confirmations.delete.heading": "Delete post", + "confirmations.delete.heading": "מחק הודעה", "confirmations.delete.message": "למחוק את ההודעה?", - "confirmations.delete_list.confirm": "Delete", - "confirmations.delete_list.message": "Are you sure you want to permanently delete this list?", + "confirmations.delete_list.confirm": "מחק רשימה", + "confirmations.delete_list.message": "האם אתה בטוח שברצונך למחוק רשימה זו לצמיתות?", "confirmations.domain_block.confirm": "הסתר קהילה שלמה", "confirmations.domain_block.message": "באמת באמת לחסום את כל קהילת {domain}? ברב המקרים השתקות נבחרות של מספר משתמשים מסויימים צריכה להספיק.", "confirmations.mute.confirm": "להשתיק", "confirmations.mute.message": "להשתיק את {name}?", - "confirmations.redraft.confirm": "Delete & redraft", - "confirmations.redraft.message": "Are you sure you want to delete this status and re-draft it? You will lose all replies, boosts and favourites to it.", - "confirmations.register.needs_approval": "Your account will be manually approved by an admin. Please be patient while we review your details.", - "confirmations.register.needs_confirmation": "Please check your inbox at {email} for confirmation instructions. You will need to verify your email address to continue.", - "confirmations.reply.confirm": "Reply", - "confirmations.reply.message": "Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?", + "confirmations.redraft.confirm": "מחק ותנסח מחדש", + "confirmations.redraft.message": "האם אתה בטוח שברצונך למחוק את הפוסט הזה ולנסח אותו מחדש? אתה תאבד את כל התגובות,ההדוהודים והלייקים שלו.", + "confirmations.register.needs_approval": "החשבון שלך יאושר באופן ידני על ידי מנהל. אנא התאזר בסבלנות בזמן שאנו בודקים את הפרטים שלך.", + "confirmations.register.needs_confirmation": "אנא בדוק את תיבת הדואר הנכנס שלך בכתובת {email} לקבלת הוראות אישור. תצטרך לאמת את כתובת הדואר שלך כדי להמשיך.", + "confirmations.reply.confirm": "הגב", + "confirmations.reply.message": "כתיבת תגובה עכשיו תחליף את ההודעה שאתה כותב כעת. האם אתה בטוח שאתה רוצה להמשיך?", "confirmations.unfollow.confirm": "להפסיק מעקב", "confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?", - "crypto_donate.explanation_box.message": "{siteTitle} accepts cryptocurrency donations. You may send a donation to any of the addresses below. Thank you for your support!", - "crypto_donate.explanation_box.title": "Sending cryptocurrency donations", - "crypto_donate_panel.actions.more": "Click to see {count} more {count, plural, one {wallet} other {wallets}}", - "crypto_donate_panel.heading": "Donate Cryptocurrency", - "crypto_donate_panel.intro.message": "{siteTitle} accepts cryptocurrency donations to fund our service. Thank you for your support!", - "datepicker.hint": "Scheduled to post at…", - "developers.navigation.app_create_label": "Create an app", - "developers.navigation.intentional_error_label": "Trigger an error", - "direct.search_placeholder": "Send a message to…", - "directory.federated": "From known fediverse", - "directory.local": "From {domain} only", - "directory.new_arrivals": "New arrivals", - "directory.recently_active": "Recently active", - "donate": "Donate", - "donate_crypto": "Donate cryptocurrency", - "edit_federation.followers_only": "Hide posts except to followers", - "edit_federation.force_nsfw": "Force attachments to be marked sensitive", - "edit_federation.media_removal": "Strip media", - "edit_federation.reject": "Reject all activities", - "edit_federation.save": "Save", - "edit_federation.success": "{host} federation was updated", - "edit_federation.unlisted": "Force posts unlisted", - "edit_profile.error": "Profile update failed", - "edit_profile.fields.accepts_email_list_label": "Subscribe to newsletter", - "edit_profile.fields.avatar_label": "Avatar", - "edit_profile.fields.bio_label": "Bio", - "edit_profile.fields.bio_placeholder": "Tell us about yourself.", - "edit_profile.fields.bot_label": "This is a bot account", - "edit_profile.fields.discoverable_label": "Allow account discovery", - "edit_profile.fields.display_name_label": "Display name", - "edit_profile.fields.display_name_placeholder": "Name", - "edit_profile.fields.header_label": "Header", - "edit_profile.fields.hide_network_label": "Hide network", - "edit_profile.fields.locked_label": "Lock account", - "edit_profile.fields.meta_fields.content_placeholder": "Content", - "edit_profile.fields.meta_fields.label_placeholder": "Label", - "edit_profile.fields.meta_fields_label": "Profile metadata", - "edit_profile.fields.stranger_notifications_label": "Block notifications from strangers", - "edit_profile.fields.verified_display_name": "Verified users may not update their display name", - "edit_profile.hints.accepts_email_list": "Opt-in to news and marketing updates.", - "edit_profile.hints.avatar": "PNG, GIF or JPG. Will be downscaled to {size}", - "edit_profile.hints.bot": "This account mainly performs automated actions and might not be monitored", - "edit_profile.hints.discoverable": "Display account in profile directory and allow indexing by external services", - "edit_profile.hints.header": "PNG, GIF or JPG. Will be downscaled to {size}", - "edit_profile.hints.hide_network": "Who you follow and who follows you will not be shown on your profile", - "edit_profile.hints.locked": "Requires you to manually approve followers", - "edit_profile.hints.meta_fields": "You can have up to {count, plural, one {# item} other {# items}} displayed as a table on your profile", - "edit_profile.hints.stranger_notifications": "Only show notifications from people you follow", - "edit_profile.meta_fields.add": "Add new item", - "edit_profile.save": "Save", - "edit_profile.success": "Profile saved!", + "crypto_donate.explanation_box.message": "{siteTitle} מקבל תרומות של מטבעות קריפטוגרפיים. ניתן לשלוח תרומה לכל אחת מהכתובות למטה. תודה על תמיכתך!", + "crypto_donate.explanation_box.title": "שליחת תרומות מטבעות קריפטוגרפיים", + "crypto_donate_panel.actions.more": "לחץ כדי לראות {count} ועוד {count, plural, one {wallet} other {wallets}}", + "crypto_donate_panel.heading": "תרום מטבעות קריפטו", + "crypto_donate_panel.intro.message": "{siteTitle} מקבל תרומות של מטבעות קריפטוגרפיים כדי לממן את השירות שלנו. תודה על תמיכתך!", + "datepicker.hint": "מתוכנן לפרסם ב...", + "developers.navigation.app_create_label": "צור אפליקציה", + "developers.navigation.intentional_error_label": "הפעלת שגיאה", + "direct.search_placeholder": "שלח הודעה ל...", + "directory.federated": "מהפדיברס הידוע", + "directory.local": "מ{domain} בלבד", + "directory.new_arrivals": "מגיעים חדשים", + "directory.recently_active": "פעיל לאחרונה", + "donate": "תרומה", + "donate_crypto": "תרום מטבע קריפטוגרפי", + "edit_federation.followers_only": "הסתר פוסטים למעט מעוקבים", + "edit_federation.force_nsfw": "כפה על סימון קבצים מצורפים כרגישים", + "edit_federation.media_removal": "הסר מדיה", + "edit_federation.reject": "דחה את כל הפעילויות", + "edit_federation.save": "שמור", + "edit_federation.success": "הפדרציה של {host} עודכנה", + "edit_federation.unlisted": "לכפות פוסטים כלא רשומים", + "edit_profile.error": "עדכון הפרופיל נכשל", + "edit_profile.fields.accepts_email_list_label": "הירשם לעדכונים", + "edit_profile.fields.avatar_label": "אווטאר", + "edit_profile.fields.bio_label": "ביוגרפיה", + "edit_profile.fields.bio_placeholder": "ספר לנו על עצמך.", + "edit_profile.fields.bot_label": "זה חשבון בוט", + "edit_profile.fields.discoverable_label": "אפשר גילוי חשבון", + "edit_profile.fields.display_name_label": "שם תצוגה", + "edit_profile.fields.display_name_placeholder": "שם", + "edit_profile.fields.header_label": "כותרת", + "edit_profile.fields.hide_network_label": "הסתר רשת", + "edit_profile.fields.locked_label": "נעל חשבון", + "edit_profile.fields.meta_fields.content_placeholder": "תוכן", + "edit_profile.fields.meta_fields.label_placeholder": "תווית", + "edit_profile.fields.meta_fields_label": "מטא נתונים של פרופיל", + "edit_profile.fields.stranger_notifications_label": "חסום התראות מזרים", + "edit_profile.fields.verified_display_name": "משתמשים מאומתים לא יכולים לעדכן את שם התצוגה שלהם", + "edit_profile.hints.accepts_email_list": "הצטרפו לעדכוני חדשות ועדכונים שיווקיים.", + "edit_profile.hints.avatar": "PNG, GIF או JPG. יוקטן ל-{size}", + "edit_profile.hints.bot": "חשבון זה מבצע בעיקר פעולות אוטומטיות וייתכן שלא יהיה פיקוח", + "edit_profile.hints.discoverable": "הצג חשבון בספריית הפרופילים ואפשר הוספה לאינדקס על ידי שירותים חיצוניים", + "edit_profile.hints.header": "PNG, GIF או JPG. יוקטן ל-{size}", + "edit_profile.hints.hide_network": "מי אתה עוקב ומי עוקב אחריך לא יוצג בפרופיל שלך", + "edit_profile.hints.locked": "מחייב אותך לאשר עוקבים באופן ידני", + "edit_profile.hints.meta_fields": "תוכל להציג עד {count, plural, one {# item} other {# items}} אחרים כטבלה בפרופיל שלך", + "edit_profile.hints.stranger_notifications": "הצג רק התראות מאנשים שאתה עוקב אחריהם", + "edit_profile.meta_fields.add": "הוסף פריט חדש", + "edit_profile.save": "שמירה", + "edit_profile.success": "הפרופיל נשמר!", "embed.instructions": "ניתן להטמיע את ההודעה באתרך ע\"י העתקת הקוד שלהלן.", "embed.preview": "דוגמא כיצד זה יראה:", "emoji_button.activity": "פעילות", @@ -371,102 +371,102 @@ "emoji_button.search_results": "תוצאות חיפוש", "emoji_button.symbols": "סמלים", "emoji_button.travel": "טיולים ואתרים", - "empty_column.account_blocked": "You are blocked by @{accountUsername}.", - "empty_column.account_favourited_statuses": "This user doesn't have any liked posts yet.", - "empty_column.account_timeline": "No posts here!", - "empty_column.account_unavailable": "Profile unavailable", - "empty_column.aliases": "You haven't created any account alias yet.", - "empty_column.aliases.suggestions": "There are no account suggestions available for the provided term.", - "empty_column.blocks": "You haven't blocked any users yet.", - "empty_column.bookmarks": "You don't have any bookmarks yet. When you add one, it will show up here.", - "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.domain_blocks": "There are no hidden domains yet.", - "empty_column.favourited_statuses": "You don't have any favorite posts yet. When you favorite one, it will show up here.", - "empty_column.favourites": "No one has favorited this post yet. When someone does, they will show up here.", - "empty_column.filters": "You haven't created any muted words yet.", - "empty_column.follow_recommendations": "Looks like no suggestions could be generated for you. You can try using search to look for people you might know or explore trending hashtags.", - "empty_column.follow_requests": "You don't have any follow requests yet. When you receive one, it will show up here.", - "empty_column.group": "There is nothing in this group yet. When members of this group make new posts, they will appear here.", + "empty_column.account_blocked": "אתה נחסם על ידי @{accountUsername}.", + "empty_column.account_favourited_statuses": "למשתמש הזה אין עדיין פוסטים שאהב.", + "empty_column.account_timeline": "אין כאן פוסטים!", + "empty_column.account_unavailable": "הפרופיל אינו זמין", + "empty_column.aliases": "עדיין לא יצרת שום כינוי חשבון.", + "empty_column.aliases.suggestions": "אין הצעות לחשבון זמינות עבור המונח שסופק.", + "empty_column.blocks": "עדיין לא חסמת אף משתמש.", + "empty_column.bookmarks": "עדיין אין לך סימניות. כאשר אתה מוסיף אחד, הוא יופיע כאן.", + "empty_column.community": "טור הסביבה ריק. יש לפרסם משהו כדי שדברים יתחילו להתגלגל!", + "empty_column.direct": "עדיין אין לך הודעות ישירות. כאשר אתה שולח או מקבל אחד, הם יופיעו כאן.", + "empty_column.domain_blocks": "אין עדיין דומיינים נסתרים.", + "empty_column.favourited_statuses": "עדיין אין לך פוסטים שאהבת. כאשר אתה עושה לייק, הם יופיעו כאן.", + "empty_column.favourites": "אף אחד עדיין לא סימן את הפוסט הזה כאהוב. כשמישהו יעשה זאת, הוא יופיע כאן.", + "empty_column.filters": "עדיין לא יצרת מילים מושתקות.", + "empty_column.follow_recommendations": "נראה שלא ניתן היה ליצור עבורך הצעות. אתה יכול לנסות להשתמש בחיפוש כדי לחפש אנשים שאתה עשוי להכיר או לחקור תגי האשטאג פופולריים.", + "empty_column.follow_requests": "עדיין אין לך בקשות מעקב. כשתקבל אחד, הוא יופיע כאן.", + "empty_column.group": "עדיין אין כלום בקבוצה הזו. כאשר חברי הקבוצה הזו מעלים פוסטים חדשים, הם יופיעו כאן.", "empty_column.hashtag": "אין כלום בהאשתג הזה עדיין.", - "empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר חצוצרנים אחרים.", - "empty_column.home.local_tab": "the {site_title} tab", - "empty_column.list": "אין עדיין מאום ברשימה.", - "empty_column.lists": "You don't have any lists yet. When you create one, it will show up here.", - "empty_column.mutes": "You haven't muted any users yet.", - "empty_column.notifications": "אין התראות עדיין. יאללה, הגיע הזמן להתחיל להתערבב.", + "empty_column.home": "אף אחד לא במעקב עדיין. אפשר לבקר ב{public} או להשתמש בחיפוש כדי להתחיל ולהכיר משתמשים אחרים.", + "empty_column.home.local_tab": "הכרטיסייה {site_title} של", + "empty_column.list": "אין עדיין כלום ברשימה.", + "empty_column.lists": "עדיין אין לך רשימות. כאשר אתה יוצר אחד, הוא יופיע כאן.", + "empty_column.mutes": "עדיין לא השתקת אף משתמש.", + "empty_column.notifications": "אין התראות.", "empty_column.public": "אין פה כלום! כדי למלא את הטור הזה אפשר לכתוב משהו, או להתחיל לעקוב אחרי אנשים מקהילות אחרות", - "empty_column.remote": "There is nothing here! Manually follow users from {instance} to fill it up.", - "empty_column.scheduled_statuses": "You don't have any scheduled statuses yet. When you add one, it will show up here.", - "empty_column.search.accounts": "There are no people results for \"{term}\"", - "empty_column.search.hashtags": "There are no hashtags results for \"{term}\"", - "empty_column.search.statuses": "There are no posts results for \"{term}\"", - "export_data.actions.export": "Export", - "export_data.actions.export_blocks": "Export blocks", - "export_data.actions.export_follows": "Export follows", - "export_data.actions.export_mutes": "Export mutes", - "export_data.blocks_label": "Blocks", - "export_data.follows_label": "Follows", - "export_data.hints.blocks": "Get a CSV file containing a list of blocked accounts", - "export_data.hints.follows": "Get a CSV file containing a list of followed accounts", - "export_data.hints.mutes": "Get a CSV file containing a list of muted accounts", - "export_data.mutes_label": "Mutes", - "export_data.success.blocks": "Blocks exported successfully", - "export_data.success.followers": "Followers exported successfully", - "export_data.success.mutes": "Mutes exported successfully", - "federation_restriction.federated_timeline_removal": "Fediverse timeline removal", - "federation_restriction.followers_only": "Hidden except to followers", - "federation_restriction.full_media_removal": "Full media removal", - "federation_restriction.media_nsfw": "Attachments marked NSFW", - "federation_restriction.partial_media_removal": "Partial media removal", - "federation_restrictions.empty_message": "{siteTitle} has not restricted any instances.", - "federation_restrictions.explanation_box.message": "Normally servers on the Fediverse can communicate freely. {siteTitle} has imposed restrictions on the following servers.", - "federation_restrictions.explanation_box.title": "Instance-specific policies", - "federation_restrictions.not_disclosed_message": "{siteTitle} does not disclose federation restrictions through the API.", - "fediverse_tab.explanation_box.dismiss": "Don't show again", - "fediverse_tab.explanation_box.explanation": "{site_title} is part of the Fediverse, a social network made up of thousands of independent social media sites (aka \"servers\"). The posts you see here are from 3rd-party servers. You have the freedom to engage with them, or to block any server you don't like. Pay attention to the full username after the second @ symbol to know which server a post is from. To see only {site_title} posts, visit {local}.", - "fediverse_tab.explanation_box.title": "What is the Fediverse?", - "filters.added": "Filter added.", - "filters.context_header": "Filter contexts", - "filters.context_hint": "One or multiple contexts where the filter should apply", - "filters.filters_list_context_label": "Filter contexts:", - "filters.filters_list_delete": "Delete", - "filters.filters_list_details_label": "Filter settings:", - "filters.filters_list_drop": "Drop", - "filters.filters_list_hide": "Hide", - "filters.filters_list_phrase_label": "Keyword or phrase:", - "filters.filters_list_whole-word": "Whole word", - "filters.removed": "Filter deleted.", - "follow_recommendations.done": "Done", - "follow_recommendations.heading": "Follow people you'd like to see posts from! Here are some suggestions.", - "follow_recommendations.lead": "Posts from people you follow will show up in chronological order on your home feed. Don't be afraid to make mistakes, you can unfollow people just as easily any time!", + "empty_column.remote": "אין פה כלום! עקוב ידנית אחר משתמשים מ-{instance} כדי למלא אותו.", + "empty_column.scheduled_statuses": "עדיין אין לך סטטוסים מתוזמנים. כאשר אתה מוסיף אחד, הוא יופיע כאן.", + "empty_column.search.accounts": "אין תוצאות של אנשים עבור \"{term}\"", + "empty_column.search.hashtags": "אין תוצאות האשטאג עבור \"{term}\"", + "empty_column.search.statuses": "אין תוצאות פוסטים עבור \"{term}\"", + "export_data.actions.export": "ייצא נתונים", + "export_data.actions.export_blocks": "ייצא חסימות", + "export_data.actions.export_follows": "ייצא מעקבים", + "export_data.actions.export_mutes": "ייצא השתקות", + "export_data.blocks_label": "חסימות", + "export_data.follows_label": "מעקבים", + "export_data.hints.blocks": "קבל קובץ CSV המכיל רשימה של חשבונות חסומים", + "export_data.hints.follows": "קבל קובץ CSV המכיל רשימה של חשבונות במעקב", + "export_data.hints.mutes": "קבל קובץ CSV המכיל רשימה של חשבונות מושתקים", + "export_data.mutes_label": "השתקות", + "export_data.success.blocks": "חסימות יוצאו בהצלחה", + "export_data.success.followers": "מעקבים יוצאו בהצלחה", + "export_data.success.mutes": "השתקות יוצאו בהצלחה", + "federation_restriction.federated_timeline_removal": "הסרת ציר הזמן פדרטיבי", + "federation_restriction.followers_only": "מוסתר מלבד לעוקבים", + "federation_restriction.full_media_removal": "הסרת מדיה מלאה", + "federation_restriction.media_nsfw": "קבצים מצורפים מסומנים לא בטוח לעבודה", + "federation_restriction.partial_media_removal": "הסרת מדיה חלקית", + "federation_restrictions.empty_message": "{siteTitle} לא הגביל אף שרת.", + "federation_restrictions.explanation_box.message": "בדרך כלל שרתים בפדרציה יכולים לתקשר בחופשיות. {siteTitle} הטיל הגבלות על השרתים הבאים.", + "federation_restrictions.explanation_box.title": "מדיניות ספציפית לשרת", + "federation_restrictions.not_disclosed_message": "{siteTitle} אינו חושף הגבלות הפדרציה דרך ה-API.", + "fediverse_tab.explanation_box.dismiss": "אל תראה שוב", + "fediverse_tab.explanation_box.explanation": "{site_title} הוא חלק מה-Fediverse, רשת חברתית המורכבת מאלפי אתרי מדיה חברתית עצמאית (הידועה בשם \"servers\"). הפוסטים שאתה רואה כאן הם משרתים של צד שלישי. יש לך את החופש לעסוק בהם, או לחסום כל שרת שאתה לא אוהב. שימו לב לשם המשתמש המלא אחרי הסימן @ השני כדי לדעת מאיזה שרת מגיע הפוסט. כדי לראות רק פוסטים של {site_title}, בקר ב-{local}.", + "fediverse_tab.explanation_box.title": "מה זה הפדיברס?", + "filters.added": "פילטר נוסף.", + "filters.context_header": "הקשרי הפילטר", + "filters.context_hint": "הקשר אחד או מרובים שבהם הפילטר צריך לחול", + "filters.filters_list_context_label": "הקשרי הפילטר:", + "filters.filters_list_delete": "מחק פילטר", + "filters.filters_list_details_label": "הגדרות פילטר:", + "filters.filters_list_drop": "הורד", + "filters.filters_list_hide": "הסתר", + "filters.filters_list_phrase_label": "מילת מפתח או ביטוי:", + "filters.filters_list_whole-word": "מילה שלמה", + "filters.removed": "פילטר נמחק.", + "follow_recommendations.done": "בוצע", + "follow_recommendations.heading": "עקוב אחר אנשים שאתה רוצה לראות מהם פוסטים! הנה כמה הצעות.", + "follow_recommendations.lead": "פוסטים מאנשים שאתה עוקב אחריהם יופיעו בסדר כרונולוגי בפיד הביתי שלך. אל תפחד לעשות טעויות, אתה יכול לבטל את המעקב אחר אנשים באותה קלות בכל עת!", "follow_request.authorize": "קבלה", "follow_request.reject": "דחיה", - "forms.copy": "Copy", - "forms.hide_password": "Hide סיסמא", - "forms.show_password": "Show סיסמא", - "getting_started.open_source_notice": "מסטודון היא תוכנה חופשית (בקוד פתוח). ניתן לתרום או לדווח על בעיות בגיטהאב: {code_link} (v{code_version}).", - "group.detail.archived_group": "Archived group", - "group.members.empty": "This group does not has any members.", - "group.removed_accounts.empty": "This group does not has any removed accounts.", - "groups.card.join": "Join", - "groups.card.members": "Members", - "groups.card.roles.admin": "You're an admin", - "groups.card.roles.member": "You're a member", - "groups.card.view": "View", - "groups.create": "Create group", - "groups.detail.role_admin": "You're an admin", - "groups.edit": "Edit", - "groups.form.coverImage": "Upload new banner image (optional)", - "groups.form.coverImageChange": "Banner image selected", - "groups.form.create": "Create group", - "groups.form.description": "Description", - "groups.form.title": "Title", - "groups.form.update": "Update group", - "groups.join": "Join group", - "groups.leave": "Leave group", - "groups.removed_accounts": "Removed Accounts", - "groups.sidebar-panel.item.no_recent_activity": "No recent activity", + "forms.copy": "העתקה", + "forms.hide_password": "הסתר סיסמא", + "forms.show_password": "הראה סיסמא", + "getting_started.open_source_notice": "סבוניה היא תוכנה חופשית (בקוד פתוח). ניתן לתרום או לדווח על בעיות בגיטהאב: {code_link} (v{code_version}).", + "group.detail.archived_group": "קבוצה שנשמרה בארכיון", + "group.members.empty": "לקבוצה זו אין חברים.", + "group.removed_accounts.empty": "לקבוצה הזו אין חשבונות שהוסרו.", + "groups.card.join": "הצטרף", + "groups.card.members": "חברים", + "groups.card.roles.admin": "אתה מנהל", + "groups.card.roles.member": "אתה חבר", + "groups.card.view": "לצפות", + "groups.create": "צור קבוצה", + "groups.detail.role_admin": "אתה מנהל", + "groups.edit": "ערוך", + "groups.form.coverImage": "העלה תמונת באנר חדשה (אופציונלי)", + "groups.form.coverImageChange": "נבחרה תמונת באנר", + "groups.form.create": "צור קבוצה", + "groups.form.description": "תיאור", + "groups.form.title": "כותרת", + "groups.form.update": "עדכן קבוצה", + "groups.join": "הצטרף לקבוצה", + "groups.leave": "עזוב קבוצה", + "groups.removed_accounts": "חשבונות שהוסרו", + "groups.sidebar-panel.item.no_recent_activity": "אין פעילות לאחרונה", "groups.sidebar-panel.item.view": "new posts", "groups.sidebar-panel.show_all": "Show all", "groups.sidebar-panel.title": "Groups You're In", @@ -958,18 +958,18 @@ "upload_error.limit": "File upload limit exceeded.", "upload_error.poll": "File upload not allowed with polls.", "upload_form.description": "תיאור לכבדי ראיה", - "upload_form.preview": "Preview", + "upload_form.preview": "תצוגה מקדימה", "upload_form.undo": "ביטול", "upload_progress.label": "עולה...", "video.close": "סגירת וידאו", - "video.download": "Download file", + "video.download": "הורד קובץ", "video.exit_fullscreen": "יציאה ממסך מלא", "video.expand": "להרחיב וידאו", - "video.fullscreen": "Full screen", + "video.fullscreen": "מסך מלא", "video.hide": "להסתיר וידאו", "video.mute": "השתקת צליל", - "video.pause": "Pause", + "video.pause": "השהיה", "video.play": "ניגון", "video.unmute": "החזרת צליל", - "who_to_follow.title": "Who To Follow" + "who_to_follow.title": "מי לעקוב" } From 58850f1d8e9c5bccb5e4c124562d76711012b9e9 Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 3 Feb 2022 05:23:12 +0000 Subject: [PATCH 02/30] Fix icons to show in the picker for promotional items --- .../soapbox_config/components/icon_picker_dropdown.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js index f5c863858..6c123c2ee 100644 --- a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js +++ b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js @@ -69,7 +69,9 @@ class IconPickerMenu extends React.PureComponent { // Nice and dirty hack to display the icons c.querySelectorAll('button.emoji-mart-emoji > span').forEach(elem => { - elem.innerHTML = ``; + const newIcon = document.createElement('span'); + newIcon.innerHTML = ``; + elem.parentNode.replaceChild(newIcon, elem); }); } From e6ca4ba299fa002dc108a138176f5fa83c544210 Mon Sep 17 00:00:00 2001 From: Sean Date: Thu, 3 Feb 2022 05:25:59 +0000 Subject: [PATCH 03/30] Add css to center only the icons created by the hack in icon_picker_dropdown.js --- app/styles/emoji_picker.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/styles/emoji_picker.scss b/app/styles/emoji_picker.scss index 8e6fe8777..8ba0cfdb4 100644 --- a/app/styles/emoji_picker.scss +++ b/app/styles/emoji_picker.scss @@ -344,4 +344,8 @@ height: 22px; text-align: center; } + + .fa-hack { + margin: 0 auto; + } } From ea0d6484a6378172d2609e7b4504d7ce6fbf3a63 Mon Sep 17 00:00:00 2001 From: Sean <10513973-goldendemise@users.noreply.gitlab.com> Date: Thu, 3 Feb 2022 16:06:41 +0000 Subject: [PATCH 04/30] Update app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js --- .../features/soapbox_config/components/icon_picker_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js index 6c123c2ee..4159d5974 100644 --- a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js +++ b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js @@ -68,7 +68,7 @@ class IconPickerMenu extends React.PureComponent { if (!c) return; // Nice and dirty hack to display the icons - c.querySelectorAll('button.emoji-mart-emoji > span').forEach(elem => { + c.querySelectorAll('button.emoji-mart-emoji > img').forEach(elem => { const newIcon = document.createElement('span'); newIcon.innerHTML = ``; elem.parentNode.replaceChild(newIcon, elem); From aea44e2ac6df70ffd27d5ed2309ddbe9113f2e16 Mon Sep 17 00:00:00 2001 From: Sean <10513973-goldendemise@users.noreply.gitlab.com> Date: Thu, 3 Feb 2022 16:14:36 +0000 Subject: [PATCH 05/30] Update app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js --- .../features/soapbox_config/components/icon_picker_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js index 4159d5974..56258f5ad 100644 --- a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js +++ b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js @@ -69,7 +69,7 @@ class IconPickerMenu extends React.PureComponent { // Nice and dirty hack to display the icons c.querySelectorAll('button.emoji-mart-emoji > img').forEach(elem => { - const newIcon = document.createElement('span'); + const newIcon = document.createElement('span'); newIcon.innerHTML = ``; elem.parentNode.replaceChild(newIcon, elem); }); From 4c522ca1488f8dea2120783276b877e007e6aba1 Mon Sep 17 00:00:00 2001 From: Sean <10513973-goldendemise@users.noreply.gitlab.com> Date: Fri, 4 Feb 2022 17:43:01 +0000 Subject: [PATCH 06/30] fix spacing --- app/styles/emoji_picker.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/emoji_picker.scss b/app/styles/emoji_picker.scss index 8ba0cfdb4..9fb1a326c 100644 --- a/app/styles/emoji_picker.scss +++ b/app/styles/emoji_picker.scss @@ -345,7 +345,7 @@ text-align: center; } - .fa-hack { + .fa-hack { margin: 0 auto; } } From bf0a7d7bae90a68a82e2c7e421e2ad802fbff7d0 Mon Sep 17 00:00:00 2001 From: NEETzsche <8018262-NEETzsche@users.noreply.gitlab.com> Date: Sat, 5 Feb 2022 20:36:25 +0000 Subject: [PATCH 07/30] State why you can't follow someone, don't just disable the button --- app/soapbox/features/ui/components/action_button.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/soapbox/features/ui/components/action_button.js b/app/soapbox/features/ui/components/action_button.js index c3e1cc76f..f64a5b828 100644 --- a/app/soapbox/features/ui/components/action_button.js +++ b/app/soapbox/features/ui/components/action_button.js @@ -25,6 +25,7 @@ const messages = defineMessages({ requested_small: { id: 'account.requested_small', defaultMessage: 'Awaiting approval' }, unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' }, edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, + blocked: { id: 'account.blocked', defaultMessage: 'Blocked' }, }); const mapStateToProps = state => { @@ -132,8 +133,9 @@ class ActionButton extends ImmutablePureComponent { return ); From a14f21800946d74f45acda7409bd4ec42eb92c71 Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 01:57:12 +0000 Subject: [PATCH 08/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 688 ++++++++++++++++++------------------ 1 file changed, 344 insertions(+), 344 deletions(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 36262022b..47d76c275 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -71,7 +71,7 @@ "admin.dashcounters.retention_label": "שימור משתמשים", "admin.dashcounters.status_count_label": "פוסטים", "admin.dashcounters.user_count_label": "סך כל המשתמשים", - "admin.dashwidgets.email_list_header": "רשימת דואר", + "admin.dashwidgets.email_list_header": "רשימת אימייל", "admin.dashwidgets.software_header": "תוכנה", "admin.latest_accounts_panel.expand_message": "לחץ כדי לראות {count} עוד{count, plural, one {account} other {accounts}}", "admin.latest_accounts_panel.title": "חשבונות אחרונים", @@ -103,12 +103,12 @@ "admin.users.actions.unsuggest_user": "הסר הצעה @{name}", "admin.users.actions.unverify_user": "הסר אימות @{name}", "admin.users.actions.verify_user": "אמת @{name}", - "admin.users.user_deactivated_message": "@{acct} was deactivated", - "admin.users.user_deleted_message": "@{acct} was deleted", - "admin.users.user_suggested_message": "@{acct} was suggested", - "admin.users.user_unsuggested_message": "@{acct} was unsuggested", - "admin.users.user_unverified_message": "@{acct} was unverified", - "admin.users.user_verified_message": "@{acct} was verified", + "admin.users.user_deactivated_message": "@{acct} הושבת", + "admin.users.user_deleted_message": "@{acct} נמחק", + "admin.users.user_suggested_message": "הוצע @{acct}", + "admin.users.user_unsuggested_message": "‎@{acct} הוסר מהצעה", + "admin.users.user_unverified_message": "@{acct} הוסר מאימות", + "admin.users.user_verified_message": "@{acct} אומת", "admin_nav.awaiting_approval": "מחכה לאישור", "admin_nav.dashboard": "לוח מחוונים", "admin_nav.reports": "דיווחים", @@ -260,7 +260,7 @@ "compose_form.poll.switch_to_multiple": "שנה סקר כדי לאפשר אפשרויות בחירה מרובות", "compose_form.poll.switch_to_single": "שנה סקר כדי לאפשר בחירה יחידה", "compose_form.publish": "ללחוש", - "compose_form.publish_loud": "לחצרץ!", + "compose_form.publish_loud": "פרסם!", "compose_form.schedule": "לתזמן", "compose_form.scheduled_statuses.click_here": "לחץ כאן", "compose_form.scheduled_statuses.message": "יש לך פוסטים מתוזמנים. {לחץ_כאן} כדי לראות אותם.", @@ -467,258 +467,258 @@ "groups.leave": "עזוב קבוצה", "groups.removed_accounts": "חשבונות שהוסרו", "groups.sidebar-panel.item.no_recent_activity": "אין פעילות לאחרונה", - "groups.sidebar-panel.item.view": "new posts", - "groups.sidebar-panel.show_all": "Show all", - "groups.sidebar-panel.title": "Groups You're In", - "groups.tab_admin": "Manage", - "groups.tab_featured": "Featured", - "groups.tab_member": "Member", - "hashtag.column_header.tag_mode.all": "and {additional}", - "hashtag.column_header.tag_mode.any": "or {additional}", - "hashtag.column_header.tag_mode.none": "without {additional}", - "header.about.label": "About", - "header.back_to.label": "Back to {siteTitle}", - "header.home.label": "Home", - "header.login.label": "Log in", - "home.column_settings.show_direct": "Show direct messages", + "groups.sidebar-panel.item.view": "פוסטים חדשים", + "groups.sidebar-panel.show_all": "תראה הכול", + "groups.sidebar-panel.title": "קבוצות שאתה נמצא בהן", + "groups.tab_admin": "נהל", + "groups.tab_featured": "מומלצים", + "groups.tab_member": "חבר", + "hashtag.column_header.tag_mode.all": "ו-{additional}", + "hashtag.column_header.tag_mode.any": "או {additional}", + "hashtag.column_header.tag_mode.none": "בלי {additional}", + "header.about.label": "אודות", + "header.back_to.label": "חזור ל-{siteTitle}", + "header.home.label": "בית", + "header.login.label": "התחברות", + "home.column_settings.show_direct": "הצג הודעות ישירות", "home.column_settings.show_reblogs": "הצגת הדהודים", "home.column_settings.show_replies": "הצגת תגובות", - "home.column_settings.title": "Home settings", - "home_column.lists": "Lists", - "home_column_header.all": "All", - "home_column_header.fediverse": "Fediverse", + "home.column_settings.title": "הגדרות ציר זמן ביתי", + "home_column.lists": "רשימותs", + "home_column_header.all": "הכל", + "home_column_header.fediverse": "ציר זמן פדרטיבי", "home_column_header.home": "בבית", - "icon_button.icons": "Icons", - "icon_button.label": "Select icon", - "icon_button.not_found": "No icons!! (╯°□°)╯︵ ┻━┻", - "import_data.actions.import": "Import", - "import_data.actions.import_blocks": "Import blocks", - "import_data.actions.import_follows": "Import follows", - "import_data.actions.import_mutes": "Import mutes", - "import_data.blocks_label": "Blocks", - "import_data.follows_label": "Follows", - "import_data.hints.blocks": "CSV file containing a list of blocked accounts", - "import_data.hints.follows": "CSV file containing a list of followed accounts", - "import_data.hints.mutes": "CSV file containing a list of muted accounts", - "import_data.mutes_label": "Mutes", - "import_data.success.blocks": "Blocks imported successfully", - "import_data.success.followers": "Followers imported successfully", - "import_data.success.mutes": "Mutes imported successfully", + "icon_button.icons": "סמלים", + "icon_button.label": "בחר סמל", + "icon_button.not_found": "אין סימנים!! (╯°□°)╯︵ ┻━┻", + "import_data.actions.import": "יבא", + "import_data.actions.import_blocks": "יבא חסימות", + "import_data.actions.import_follows": "יבא מעקבים", + "import_data.actions.import_mutes": "יבא השתקות", + "import_data.blocks_label": "חסימות", + "import_data.follows_label": "מעקבים", + "import_data.hints.blocks": "קובץ CSV המכיל רשימה של חשבונות חסומים", + "import_data.hints.follows": "קובץ CSV המכיל רשימה של חשבונות במעקב", + "import_data.hints.mutes": "קובץ CSV המכיל רשימה של חשבונות מושתקים", + "import_data.mutes_label": "השתקות", + "import_data.success.blocks": "חסימות יובאו בהצלחה", + "import_data.success.followers": "מעקבים יובאו בהצלחה", + "import_data.success.mutes": "השתקות יובאו בהצלחה", "intervals.full.days": "{number, plural, one {# day} other {# days}}", "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", - "introduction.federation.action": "Next", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.interactions.action": "Finish tutorial!", - "introduction.interactions.favourite.headline": "Favorite", - "introduction.interactions.favourite.text": "You can save a post for later, and let the author know that you liked it, by favoriting it.", - "introduction.interactions.reblog.headline": "Repost", - "introduction.interactions.reblog.text": "You can share other people's posts with your followers by reposting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own posts, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", + "introduction.federation.action": "הבא", + "introduction.federation.home.headline": "בית", + "introduction.federation.home.text": "פוסטים מאנשים שאתה עוקב אחריהם יופיעו בפיד הביתי שלך. אתה יכול לעקוב אחר כל אחד בכל שרת!", + "introduction.interactions.action": "סיים את ההדרכה!", + "introduction.interactions.favourite.headline": "לייק", + "introduction.interactions.favourite.text": "אתה יכול לשמור פוסט למועד מאוחר יותר, ולהודיע למחבר שאהבת אותואת הפוסט, על ידי .לחיצת לייק", + "introduction.interactions.reblog.headline": "להדהד", + "introduction.interactions.reblog.text": "אתה יכול לשתף פוסטים של אנשים אחרים עם העוקבים שלך על ידי הדהוד הפוסט שלהם.", + "introduction.interactions.reply.headline": "הגב", + "introduction.interactions.reply.text": "אתה יכול להשיב לפוסטים של אנשים אחרים ושלך, שיקשרו אותם יחדיו בשיחה.", + "introduction.welcome.action": "הבא נתחיל", + "introduction.welcome.headline": "צעדים ראשונים", + "introduction.welcome.text": "ברוכים הבאים ל-Fediverse! תוך כמה רגעים, תוכל לשדר הודעות ולדבר עם חבריך במגוון רחב של שרתים. אבל השרת הזה, {domain}, הוא מיוחד - הוא מארח את הפרופיל שלך, אז זכור את שמו.", "keyboard_shortcuts.back": "ניווט חזרה", - "keyboard_shortcuts.blocked": "to open blocked users list", + "keyboard_shortcuts.blocked": "לפתיחת רשימת משתמשים חסומים", "keyboard_shortcuts.boost": "להדהד", "keyboard_shortcuts.compose": "להתמקד בתיבת חיבור ההודעות", "keyboard_shortcuts.down": "לנוע במורד הרשימה", - "keyboard_shortcuts.enter": "to open post", - "keyboard_shortcuts.favourite": "לחבב", - "keyboard_shortcuts.favourites": "to open favorites list", - "keyboard_shortcuts.heading": "Keyboard Shortcuts", - "keyboard_shortcuts.home": "to open home timeline", + "keyboard_shortcuts.enter": "לפתוח פוסט", + "keyboard_shortcuts.favourite": "לייק", + "keyboard_shortcuts.favourites": "לפתוח את רשימת הלייקים", + "keyboard_shortcuts.heading": "קיצורי דרך במקלדת", + "keyboard_shortcuts.home": "לפתוח את ציר הזמן הביתי", "keyboard_shortcuts.hotkey": "מקש קיצור", "keyboard_shortcuts.legend": "להציג את הפירוש", - "keyboard_shortcuts.mention": "לאזכר את המחבר(ת)", - "keyboard_shortcuts.muted": "to open muted users list", - "keyboard_shortcuts.my_profile": "to open your profile", - "keyboard_shortcuts.notifications": "to open notifications column", - "keyboard_shortcuts.open_media": "to open media", - "keyboard_shortcuts.pinned": "to open pinned posts list", - "keyboard_shortcuts.profile": "to open author's profile", - "keyboard_shortcuts.react": "to react", + "keyboard_shortcuts.mention": "לאזכר את המחבר", + "keyboard_shortcuts.muted": "לפתוח את רשימת המשתמשים המושתקים", + "keyboard_shortcuts.my_profile": "לפתוח את הפרופיל שלך", + "keyboard_shortcuts.notifications": "לפתוח את עמודת ההתראות", + "keyboard_shortcuts.open_media": "לפתוח מדיה", + "keyboard_shortcuts.pinned": "לפתוח את רשימת הפוסטים המוצמדים", + "keyboard_shortcuts.profile": "לפתוח את פרופיל המחבר", + "keyboard_shortcuts.react": "להגיב", "keyboard_shortcuts.reply": "לענות", - "keyboard_shortcuts.requests": "to open follow requests list", + "keyboard_shortcuts.requests": "לפתוח את רשימת בקשות המעקב", "keyboard_shortcuts.search": "להתמקד בחלון החיפוש", - "keyboard_shortcuts.toggle_hidden": "to show/hide text behind CW", - "keyboard_shortcuts.toggle_sensitivity": "to show/hide media", - "keyboard_shortcuts.toot": "להתחיל חיצרוץ חדש", + "keyboard_shortcuts.toggle_hidden": "להציג/להסתיר טקסט מאחורי אזהרת תוכן", + "keyboard_shortcuts.toggle_sensitivity": "להציג/להסתיר מדיה", + "keyboard_shortcuts.toot": "להתחיל פוסט חדש", "keyboard_shortcuts.unfocus": "לצאת מתיבת חיבור/חיפוש", "keyboard_shortcuts.up": "לנוע במעלה הרשימה", "lightbox.close": "סגירה", "lightbox.next": "הלאה", "lightbox.previous": "הקודם", - "lightbox.view_context": "View context", - "list.click_to_add": "Click here to add people", - "list.label": "Select list…", - "list.select": "Select list", - "list_adder.header_title": "Add or Remove from Lists", - "lists.account.add": "Add to list", - "lists.account.remove": "Remove from list", - "lists.edit": "Edit list", - "lists.edit.submit": "Change title", - "lists.new.create": "Add list", - "lists.new.create_title": "Create", - "lists.new.save_title": "Save Title", - "lists.new.title_placeholder": "New list title", - "lists.search": "Search among people you follow", - "lists.subheading": "Your lists", + "lightbox.view_context": "הצג את ההקשר", + "list.click_to_add": "לחץ כאן כדי להוסיף אנשים", + "list.label": "בחר רשימה...", + "list.select": "בחר רשימה", + "list_adder.header_title": "הוסף או הסר מהרשימה", + "lists.account.add": "הוסף לרשימה", + "lists.account.remove": "הסר מהרשימה", + "lists.edit": "ערוך רשימה", + "lists.edit.submit": "שנה כותרת", + "lists.new.create": "הוסף רשימה", + "lists.new.create_title": "צור כותרת", + "lists.new.save_title": "שמור כותרת", + "lists.new.title_placeholder": "כותרת רשימה חדשה", + "lists.search": "חפש בין אנשים שאתה עוקב אחריהם", + "lists.subheading": "הרשימות שלך", "loading_indicator.label": "טוען...", - "login.fields.instance_label": "Instance", + "login.fields.instance_label": "שרת", "login.fields.instance_placeholder": "example.com", - "login.fields.otp_code_hint": "Enter the two-factor code generated by your phone app or use one of your recovery codes", - "login.fields.otp_code_label": "Two-factor code:", - "login.fields.password_placeholder": "Password", - "login.fields.username_placeholder": "Username", - "login.log_in": "Log in", - "login.otp_log_in": "OTP Login", - "login.otp_log_in.fail": "Invalid code, please try again.", - "login.reset_password_hint": "Trouble logging in?", + "login.fields.otp_code_hint": "הזן את קוד שני הגורמים שנוצר על ידי אפליקציות הטלפון שלך או השתמש באחד מקודי השחזור שלך", + "login.fields.otp_code_label": "קוד דו גורמי:", + "login.fields.password_placeholder": "סיסמא", + "login.fields.username_placeholder": "שם משתמש", + "login.log_in": "התחברות", + "login.otp_log_in": "התחברות OTP", + "login.otp_log_in.fail": "קוד לא חוקי, אנא נסה שוב.", + "login.reset_password_hint": "בעיה בהתחברות?", "media_gallery.toggle_visible": "נראה בלתי נראה", - "media_panel.empty_message": "No media found.", - "media_panel.title": "Media", - "mfa.mfa_disable_enter_password": "Enter your current סיסמא to disable two-factor auth:", - "mfa.mfa_setup_enter_password": "Enter your current סיסמא to confirm your identity:", - "mfa.mfa_setup_scan_description": "Using your two-factor app, scan this QR code or enter text key:", - "mfa.mfa_setup_scan_key": "Key:", - "mfa.mfa_setup_scan_title": "Scan", - "mfa.mfa_setup_verify_description": "To enable two-factor authentication, enter the code from your two-factor app:", - "mfa.mfa_setup_verify_title": "Verify", - "mfa.otp_enabled_description": "You have enabled two-factor authentication via OTP.", - "mfa.otp_enabled_title": "OTP Enabled", - "mfa.setup_hint": "Follow these steps to set up multi-factor authentication on your account with OTP", - "mfa.setup_otp_title": "OTP Disabled", - "mfa.setup_recoverycodes": "Recovery codes", - "mfa.setup_warning": "Write these codes down or save them somewhere secure - otherwise you won't see them again. If you lose access to your 2FA app and recovery codes you'll be locked out of your account.", - "missing_description_modal.cancel": "Cancel", - "missing_description_modal.continue": "Post", - "missing_description_modal.text": "You have not entered a description for all attachments. Continue anyway?", + "media_panel.empty_message": "לא נמצאה מדיה.", + "media_panel.title": "מדיה", + "mfa.mfa_disable_enter_password": "הזן את הסיסמא הנוכחית שלך כדי להשבית אימות דו-גורמי:", + "mfa.mfa_setup_enter_password": "הזן את הסיסמא הנוכחית שלך כדי לאשר את זהותך:", + "mfa.mfa_setup_scan_description": "באמצעות אפליקציות שני הגורמים שלך, סרוק את קוד ה-QR הזה או הזן מפתח טקסט:", + "mfa.mfa_setup_scan_key": "מפתח:", + "mfa.mfa_setup_scan_title": "סריקה", + "mfa.mfa_setup_verify_description": "כדי להפעיל אימות דו-גורמי, הזן את הקוד מהאפליקציה הדו-גורמית שלך:", + "mfa.mfa_setup_verify_title": "אמת", + "mfa.otp_enabled_description": "הפעלת אימות דו-שלבי באמצעות OTP.", + "mfa.otp_enabled_title": "OTP מופעל", + "mfa.setup_hint": "בצע את השלבים הבאים כדי להגדיר אימות רב-גורמי בחשבון שלך באמצעות OTP", + "mfa.setup_otp_title": "OTP מושבת", + "mfa.setup_recoverycodes": "קודי שחזור", + "mfa.setup_warning": "רשום את הקודים האלה או שמור אותם במקום מאובטח - אחרת לא תראה אותם שוב. אם תאבד את הגישה לאפליקציית 2FA ולקודי השחזור שלך תינעל מחוץ לחשבון שלך.", + "missing_description_modal.cancel": "בטל", + "missing_description_modal.continue": "שלח", + "missing_description_modal.text": "לא הזנת תיאור עבור כל הקבצים המצורפים. המשך בכל זאת?", "missing_indicator.label": "לא נמצא", - "missing_indicator.sublabel": "This resource could not be found", - "morefollows.followers_label": "…and {count} more {count, plural, one {follower} other {followers}} on remote sites.", - "morefollows.following_label": "…and {count} more {count, plural, one {follow} other {follows}} on remote sites.", + "missing_indicator.sublabel": "משאב זה לא נמצא", + "morefollows.followers_label": "ו-{count} עוד {count, plural, one {follower} other {followers}} באתרים מרוחקים.", + "morefollows.following_label": "ו-{count} עוד {count, plural, one {follow} other {follows}} באתרים מרוחקים.", "mute_modal.hide_notifications": "להסתיר הודעות מחשבון זה?", - "navigation.chats": "Chats", - "navigation.dashboard": "Dashboard", - "navigation.developers": "Developers", - "navigation.direct_messages": "Messages", - "navigation.home": "Home", - "navigation.invites": "Invites", - "navigation.notifications": "Notifications", - "navigation.search": "Search", - "navigation_bar.account_aliases": "Account aliases", - "navigation_bar.admin_settings": "Admin settings", + "navigation.chats": "צ'אטים", + "navigation.dashboard": "לוח מחוונים", + "navigation.developers": "מפתחים", + "navigation.direct_messages": "הודעות", + "navigation.home": "בית", + "navigation.invites": "הזמנות", + "navigation.notifications": "התראות", + "navigation.search": "חיפוש", + "navigation_bar.account_aliases": "כיונויי חשבון", + "navigation_bar.admin_settings": "הגדרות אדמין", "navigation_bar.blocks": "חסימות", - "navigation_bar.bookmarks": "Bookmarks", - "navigation_bar.compose": "Compose new post", - "navigation_bar.compose_direct": "Direct message", - "navigation_bar.compose_reply": "Reply to post", - "navigation_bar.domain_blocks": "Hidden domains", - "navigation_bar.export_data": "Export data", + "navigation_bar.bookmarks": "סימניות", + "navigation_bar.compose": "כתוב פוסט חדש", + "navigation_bar.compose_direct": "הודעה ישירה", + "navigation_bar.compose_reply": "השב לפוסט", + "navigation_bar.domain_blocks": "דומיינים נסתרים", + "navigation_bar.export_data": "יצא נתונים", "navigation_bar.favourites": "חיבובים", - "navigation_bar.filters": "Muted words", + "navigation_bar.filters": "מילים מושתקות", "navigation_bar.follow_requests": "בקשות מעקב", - "navigation_bar.import_data": "Import data", - "navigation_bar.in_reply_to": "In reply to", + "navigation_bar.import_data": "יבא נתונים", + "navigation_bar.in_reply_to": "בתשובה ל", "navigation_bar.info": "מידע נוסף", - "navigation_bar.invites": "Invites", + "navigation_bar.invites": "הזמנות", "navigation_bar.keyboard_shortcuts": "קיצורי מקלדת", - "navigation_bar.lists": "Lists", + "navigation_bar.lists": "רשימות", "navigation_bar.logout": "יציאה", - "navigation_bar.messages": "Messages", + "navigation_bar.messages": "הודעות", "navigation_bar.mutes": "השתקות", - "navigation_bar.pins": "חיצרוצים מקובעים", + "navigation_bar.pins": "פוסטים נעוצים", "navigation_bar.preferences": "העדפות", - "navigation_bar.profile_directory": "Profile directory", - "navigation_bar.security": "Security", - "navigation_bar.soapbox_config": "Soapbox config", - "notification.chat_mention": "{name} sent you a message", - "notification.favourite": "חצרוצך חובב על ידי {name}", + "navigation_bar.profile_directory": "ספריית פרופילים", + "navigation_bar.security": "אבטחה", + "navigation_bar.soapbox_config": "תצורת סבוניה", + "notification.chat_mention": "{name} שלח לך הודעה", + "notification.favourite": "הפוסט שלך חובב על ידי {name}", "notification.follow": "{name} במעקב אחרייך", - "notification.follow_request": "{name} has requested to follow you", + "notification.follow_request": "{name} ביקש לעקוב אחריך", "notification.mention": "אוזכרת על ידי {name}", - "notification.move": "{name} moved to {targetName}", - "notification.pleroma:emoji_reaction": "{name} reacted to your post", - "notification.poll": "A poll you have voted in has ended", - "notification.reblog": "חצרוצך הודהד על ידי {name}", + "notification.move": "{name} הועבר אל {targetName}", + "notification.pleroma:emoji_reaction": "{name} הגיב לפוסט שלך", + "notification.poll": "סקר שהצבעת בו הסתיים", + "notification.reblog": "הפוסט שלך הודהד על ידי {name}", "notifications.clear": "הסרת התראות", "notifications.clear_confirmation": "להסיר את כל ההתראות? בטוח?", "notifications.column_settings.alert": "התראות לשולחן העבודה", - "notifications.column_settings.emoji_react": "Emoji reacts:", + "notifications.column_settings.emoji_react": "הגבות אימוג'י:", "notifications.column_settings.favourite": "מחובבים:", - "notifications.column_settings.filter_bar.advanced": "Display all categories", - "notifications.column_settings.filter_bar.category": "Quick filter bar", - "notifications.column_settings.filter_bar.show": "Show", + "notifications.column_settings.filter_bar.advanced": "הצג את כל הקטגוריות", + "notifications.column_settings.filter_bar.category": "סרגל סינון מהיר", + "notifications.column_settings.filter_bar.show": "הראה", "notifications.column_settings.follow": "עוקבים חדשים:", - "notifications.column_settings.follow_request": "New follow requests:", + "notifications.column_settings.follow_request": "בקשות מעקב חדשות:", "notifications.column_settings.mention": "פניות:", - "notifications.column_settings.move": "Moves:", - "notifications.column_settings.poll": "Poll results:", + "notifications.column_settings.move": "מעברים:", + "notifications.column_settings.poll": "תוצאות סקרים:", "notifications.column_settings.push": "הודעות בדחיפה", "notifications.column_settings.reblog": "הדהודים:", "notifications.column_settings.show": "הצגה בטור", "notifications.column_settings.sound": "שמע מופעל", - "notifications.column_settings.sounds": "Sounds", - "notifications.column_settings.sounds.all_sounds": "Play sound for all notifications", - "notifications.column_settings.title": "Notification settings", - "notifications.filter.all": "All", - "notifications.filter.boosts": "Reposts", - "notifications.filter.emoji_reacts": "Emoji reacts", - "notifications.filter.favourites": "Favorites", - "notifications.filter.follows": "Follows", - "notifications.filter.mentions": "Mentions", - "notifications.filter.moves": "Moves", - "notifications.filter.polls": "Poll results", - "notifications.group": "{count} notifications", - "notifications.queue_label": "Click to see {count} new {count, plural, one {notification} other {notifications}}", - "password_reset.confirmation": "Check your email for confirmation.", - "password_reset.fields.username_placeholder": "Email or username", - "password_reset.reset": "Reset סיסמא", - "pinned_statuses.none": "No pins to show.", - "poll.closed": "Closed", - "poll.refresh": "Refresh", - "poll.total_votes": "{count, plural, one {# vote} other {# votes}}", - "poll.vote": "Vote", - "poll.voted": "You voted for this answer", - "poll.votes": "{votes, plural, one {# vote} other {# votes}}", - "poll_button.add_poll": "Add a poll", - "poll_button.remove_poll": "Remove poll", - "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", - "preferences.fields.autoload_more_label": "Automatically load more items when scrolled to the bottom of the page", - "preferences.fields.autoload_timelines_label": "Automatically load new posts when scrolled to the top of the page", - "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", - "preferences.fields.content_type_label": "Post format", - "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", - "preferences.fields.demetricator_label": "Use Demetricator", - "preferences.fields.developer_label": "Developer tools", - "preferences.fields.display_media.default": "Hide media marked as sensitive", - "preferences.fields.display_media.hide_all": "Always hide media", - "preferences.fields.display_media.show_all": "Always show media", - "preferences.fields.dyslexic_font_label": "Dyslexic mode", - "preferences.fields.expand_spoilers_label": "Always expand posts marked with content warnings", - "preferences.fields.halloween_label": "Halloween mode", - "preferences.fields.language_label": "Language", - "preferences.fields.media_display_label": "Media display", - "preferences.fields.missing_description_modal_label": "Show confirmation dialog before sending a post without media descriptions", - "preferences.fields.privacy_label": "Post privacy", - "preferences.fields.reduce_motion_label": "Reduce motion in animations", - "preferences.fields.system_font_label": "Use system's default font", - "preferences.fields.underline_links_label": "Always underline links in posts", - "preferences.fields.unfollow_modal_label": "Show confirmation dialog before unfollowing someone", - "preferences.hints.content_type_markdown": "Warning: experimental!", - "preferences.hints.demetricator": "Decrease social media anxiety by hiding all numbers from the site.", - "preferences.hints.halloween": "Beware: SPOOKY! Supports light/dark toggle.", - "preferences.hints.privacy_followers_only": "Only show to followers", - "preferences.hints.privacy_public": "Everyone can see", - "preferences.hints.privacy_unlisted": "Everyone can see, but not listed on public timelines", - "preferences.options.content_type_markdown": "Markdown", - "preferences.options.content_type_plaintext": "Plain text", - "preferences.options.privacy_followers_only": "Followers-only", - "preferences.options.privacy_public": "Public", - "preferences.options.privacy_unlisted": "Unlisted", + "notifications.column_settings.sounds": "צלילים", + "notifications.column_settings.sounds.all_sounds": "הפעל צליל עבור כל ההתראות", + "notifications.column_settings.title": "הגדרות התראות", + "notifications.filter.all": "הכל", + "notifications.filter.boosts": "הדהודים", + "notifications.filter.emoji_reacts": "תגובות אימוג'י", + "notifications.filter.favourites": "לייקים", + "notifications.filter.follows": "מעקבים", + "notifications.filter.mentions": "אזכורים", + "notifications.filter.moves": "מעברים", + "notifications.filter.polls": "תוצאות סקרים", + "notifications.group": "{count} התראות", + "notifications.queue_label": "לחץ כדי לראות {count} חדשות {count, plural, one {התראה} other {התראות}}", + "password_reset.confirmation": "בדוק את האימייל שלך לאישור.", + "password_reset.fields.username_placeholder": "אימייל או שם משתמש", + "password_reset.reset": "אפס סיסמא", + "pinned_statuses.none": "אין נעוצים להראות.", + "poll.closed": "סגור", + "poll.refresh": "רענן", + "poll.total_votes": "{count, plural, one {# הצבעה} other {# הצבעות}}", + "poll.vote": "הצבע", + "poll.voted": "הצבעת בעד התשובה הזו", + "poll.votes": "{votes, plural, one {# הצבעה} other {# הצבעות}}", + "poll_button.add_poll": "הוסף סקר", + "poll_button.remove_poll": "הסר סקר", + "preferences.fields.auto_play_gif_label": "הפעל אוטומטית קובצי GIF מונפשים", + "preferences.fields.autoload_more_label": "טען אוטומטית יותר פריטים כאשר אתה מגיע לתחתית העמוד", + "preferences.fields.autoload_timelines_label": "טען אוטומטית פוסטים חדשים לאחר גלילה לראש העמוד", + "preferences.fields.boost_modal_label": "הצג תיבת אישור לפני הדהוד", + "preferences.fields.content_type_label": "פורמט פוסט", + "preferences.fields.delete_modal_label": "הצג תיבת אישור לפני מחיקת פוסט", + "preferences.fields.demetricator_label": "השתמש ב-Demetricator", + "preferences.fields.developer_label": "כלים למפתחים", + "preferences.fields.display_media.default": "הסתר מדיה שסומנה כרגישה", + "preferences.fields.display_media.hide_all": "תמיד הסתר מדיה", + "preferences.fields.display_media.show_all": "תמיד הצג מדיה", + "preferences.fields.dyslexic_font_label": "מצב דיסלקטי", + "preferences.fields.expand_spoilers_label": "הרחב תמיד פוסטים המסומנים באזהרות תוכן", + "preferences.fields.halloween_label": "מצב הלואין", + "preferences.fields.language_label": "שפה", + "preferences.fields.media_display_label": "תצוגת מדיה", + "preferences.fields.missing_description_modal_label": "הצג תיבת אישור לפני שליחת פוסט ללא תיאורי מדיה", + "preferences.fields.privacy_label": "פרטיות הפוסט", + "preferences.fields.reduce_motion_label": "הפחת תנועה באנימציות", + "preferences.fields.system_font_label": "השתמש בגופן ברירת המחדל של המערכת", + "preferences.fields.underline_links_label": "תמיד יש להדגיש קישורים בפוסטים", + "preferences.fields.unfollow_modal_label": "הצג תיבת אישור לפני ביטול המעקב אחר מישהו", + "preferences.hints.content_type_markdown": "אזהרה: ניסיוני!", + "preferences.hints.demetricator": "הפחת את חרדת המדיה החברתית על ידי הסתרת כל המספרים מהאתר.", + "preferences.hints.halloween": "היזהר: מפחיד! תומך בהחלפת אור/כהה.", + "preferences.hints.privacy_followers_only": "הצג רק לעוקבים", + "preferences.hints.privacy_public": "כולם יכולים לראות", + "preferences.hints.privacy_unlisted": "כולם יכולים לראות, אבל לא רשום על צירי זמן ציבוריים", + "preferences.options.content_type_markdown": "מארקדאון", + "preferences.options.content_type_plaintext": "טקסט רגיל", + "preferences.options.privacy_followers_only": "לעוקבים בלבד", + "preferences.options.privacy_public": "ציבורי", + "preferences.options.privacy_unlisted": "לא רשום", "privacy.change": "שינוי פרטיות ההודעה", "privacy.direct.long": "הצג רק למי שהודעה זו פונה אליו", "privacy.direct.short": "הודעה ישירה", @@ -728,96 +728,96 @@ "privacy.public.short": "פומבי", "privacy.unlisted.long": "לא יופיע בפידים הציבוריים המשותפים", "privacy.unlisted.short": "לא לפיד הכללי", - "profile_dropdown.add_account": "Add an existing account", - "profile_dropdown.logout": "Log out @{acct}", - "public.column_settings.title": "Fediverse timeline settings", - "reactions.all": "All", - "regeneration_indicator.label": "Loading…", - "regeneration_indicator.sublabel": "Your home feed is being prepared!", - "register_invite.lead": "Complete the form below to create an account.", - "register_invite.title": "You've been invited to join {siteTitle}!", - "registration.agreement": "I agree to the {tos}.", - "registration.captcha.hint": "Click the image to get a new captcha", - "registration.closed_message": "{instance} is not accepting new members", - "registration.closed_title": "Registrations Closed", - "registration.confirmation_modal.close": "Close", - "registration.fields.confirm_placeholder": "Password (again)", - "registration.fields.email_placeholder": "E-Mail address", - "registration.fields.password_placeholder": "Password", - "registration.fields.username_hint": "Only letters, numbers, and underscores are allowed.", - "registration.fields.username_placeholder": "Username", - "registration.lead": "With an account on {instance} you'll be able to follow people on any server in the fediverse.", - "registration.newsletter": "Subscribe to newsletter.", - "registration.password_mismatch": "Passwords don't match.", - "registration.reason": "Why do you want to join?", - "registration.reason_hint": "This will help us review your application", - "registration.sign_up": "Sign up", - "registration.tos": "Terms of Service", - "registration.username_unavailable": "Username is already taken.", + "profile_dropdown.add_account": "הוסף חשבון קיים", + "profile_dropdown.logout": "התנתק מ-{account}", + "public.column_settings.title": "הגדרות ציר הזמן של Fediverse", + "reactions.all": "הכל", + "regeneration_indicator.label": "טוען...", + "regeneration_indicator.sublabel": "הפיד הביתי שלך נמצא בהכנה!", + "register_invite.lead": "מלא את הטופס למטה כדי ליצור חשבון.", + "register_invite.title": "הוזמנת להצטרף ל-{siteTitle}!", + "registration.agreement": "אני מסכים ל-{tos}.", + "registration.captcha.hint": "לחץ על התמונה כדי לקבל captcha חדש", + "registration.closed_message": "{instance} אינו מקבל חברים חדשים", + "registration.closed_title": "ההרשמות סגורות", + "registration.confirmation_modal.close": "סגור", + "registration.fields.confirm_placeholder": "סיסמא (שוב)", + "registration.fields.email_placeholder": "כתובת אימייל", + "registration.fields.password_placeholder": "סיסמא", + "registration.fields.username_hint": "רק אותיות, מספרים וקווים תחתונים מותרים.", + "registration.fields.username_placeholder": "שם משתמש", + "registration.lead": "עם חשבון ב-{instance} תוכל לעקוב אחר אנשים בכל שרת ב-fediverse.", + "registration.newsletter": "הירשם לעדכונים.", + "registration.password_mismatch": "הסיסמאות אינן תואמות.", + "registration.reason": "למה אתה רוצה להצטרף?", + "registration.reason_hint": "זה יעזור לנו לבדוק את הבקשה שלך", + "registration.sign_up": "הירשם", + "registration.tos": "תנאי השירות", + "registration.username_unavailable": "שם המשתמש תפוס.", "relative_time.days": "{number}d", "relative_time.hours": "{number}h", "relative_time.just_now": "כרגע", "relative_time.minutes": "{number}m", "relative_time.seconds": "{number}s", - "remote_instance.edit_federation": "Edit federation", - "remote_instance.federation_panel.heading": "Federation Restrictions", - "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} has placed no restrictions on {host}.", - "remote_instance.federation_panel.restricted_message": "{siteTitle} blocks all activities from {host}.", - "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} has placed some restrictions on {host}.", - "remote_instance.pin_host": "Pin {host}", - "remote_instance.unpin_host": "Unpin {host}", - "remote_interaction.account_placeholder": "Enter your username@domain you want to act from", - "remote_interaction.divider": "or", - "remote_interaction.favourite": "Proceed to like", - "remote_interaction.favourite_title": "Like a post remotely", - "remote_interaction.follow": "Proceed to follow", - "remote_interaction.follow_title": "Follow {user} remotely", - "remote_interaction.poll_vote": "Proceed to vote", - "remote_interaction.poll_vote_title": "Vote in a poll remotely", - "remote_interaction.reblog": "Proceed to repost", - "remote_interaction.reblog_title": "Reblog a post remotely", - "remote_interaction.reply": "Proceed to reply", - "remote_interaction.reply_title": "Reply to a post remotely", - "remote_interaction.user_not_found_error": "Couldn't find given user", - "remote_timeline.filter_message": "You are viewing the timeline of {instance}.", + "remote_instance.edit_federation": "ערוך פדרציה", + "remote_instance.federation_panel.heading": "הגבלות הפדרציה", + "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} לא הטיל הגבלות על {host}.", + "remote_instance.federation_panel.restricted_message": "{siteTitle} חוסם את כל הפעילויות של {host}.", + "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} הטיל כמה הגבלות על {host}.", + "remote_instance.pin_host": "הצמד {מארח}", + "remote_instance.unpin_host": "בטל הצמדה של {מארח}", + "remote_interaction.account_placeholder": "הזן את username@domain שממנו ברצונך לפעול", + "remote_interaction.divider": "או", + "remote_interaction.favourite": "המשך לסמן לייק", + "remote_interaction.favourite_title": "לעשות לייק לפוסט מרחוק", + "remote_interaction.follow": "המשך לעקוב", + "remote_interaction.follow_title": "עקוב אחר {user} מרחוק", + "remote_interaction.poll_vote": "המשך להצבעה", + "remote_interaction.poll_vote_title": "הצביע בסקר מרחוק", + "remote_interaction.reblog": "המשך להדהד", + "remote_interaction.reblog_title": "הדהד פוסט מרחוק", + "remote_interaction.reply": "המשך להשיב", + "remote_interaction.reply_title": "השב לפוסט מרחוק", + "remote_interaction.user_not_found_error": "לא ניתן היה למצוא את המשתמש הנתון", + "remote_timeline.filter_message": "אתה צופה בציר הזמן של {instance}.", "reply_indicator.cancel": "ביטול", - "reply_mentions.account.add": "Add to mentions", - "reply_mentions.account.remove": "Remove from mentions", - "reply_mentions.more": "and {count} more", - "reply_mentions.reply": "Replying to {accounts}{more}", - "reply_mentions.reply_empty": "Replying to post", - "report.block": "Block {target}", - "report.block_hint": "Do you also want to block this account?", - "report.forward": "Forward to {target}", - "report.forward_hint": "The account is from another server. Send a 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:", + "reply_mentions.account.add": "הוסף לאזכורים", + "reply_mentions.account.remove": "הסר מהאזכורים", + "reply_mentions.more": "ו-{count} עוד", + "reply_mentions.reply": "משיב ל-{accounts}{more}", + "reply_mentions.reply_empty": "משיב לפוסט", + "report.block": "חסום {target}", + "report.block_hint": "האם גם אתה רוצה לחסום את החשבון הזה?", + "report.forward": "העבר אל {target}", + "report.forward_hint": "החשבון הוא משרת אחר. לשלוח עותק של הדוח גם לשם?", + "report.hint": "הדוח יישלח למנהלי השרת שלך. תוכל לספק הסבר מדוע אתה מדווח על חשבון זה למטה:", "report.placeholder": "הערות נוספות", "report.submit": "שליחה", "report.target": "דיווח", - "schedule.post_time": "Post Date/Time", - "schedule.remove": "Remove schedule", - "schedule_button.add_schedule": "Schedule post for later", - "schedule_button.remove_schedule": "Post immediately", - "scheduled_status.cancel": "Cancel", - "search.action": "Search for “{query}”", + "schedule.post_time": "פרסום תאריך/שעה", + "schedule.remove": "הסר תזמון", + "schedule_button.add_schedule": "תזמן פוסט מאוחר יותר", + "schedule_button.remove_schedule": "פרסם מיד", + "scheduled_status.cancel": "בטל", + "search.action": "חפש “{query}”", "search.placeholder": "חיפוש", - "search_results.accounts": "People", - "search_results.hashtags": "Hashtags", - "search_results.statuses": "Posts", - "search_results.top": "Top", - "security.codes.fail": "Failed to fetch backup codes", - "security.confirm.fail": "Incorrect code or סיסמא. Try again.", - "security.delete_account.fail": "Account deletion failed.", - "security.delete_account.success": "Account successfully deleted.", - "security.disable.fail": "Incorrect סיסמא. Try again.", - "security.disable_mfa": "Disable", - "security.fields.email.label": "Email address", + "search_results.accounts": "אנשים", + "search_results.hashtags": "האשטאגס", + "search_results.statuses": "פוסטים", + "search_results.top": "עליון", + "security.codes.fail": "אחזור קודי גיבוי נכשל", + "security.confirm.fail": "קוד או סיסמא שגויים. נסה שוב.", + "security.delete_account.fail": "מחיקת החשבון נכשלה.", + "security.delete_account.success": "החשבון נמחק בהצלחה.", + "security.disable.fail": "סיסמא שגויה. נסה שוב.", + "security.disable_mfa": "השבת", + "security.fields.email.label": "אימייל", "security.fields.new_password.label": "סיסמא חדשה", "security.fields.old_password.label": "סיסמא נוכחית", "security.fields.סיסמא.label": "סיסמא", "security.fields.password_confirmation.label": "סיסמא חדשה (שוב)", "security.headers.delete": "מחק חשבון", - "security.headers.tokens": "Sessions", + "security.headers.tokens": "הפעלות", "security.headers.update_email": "שנה אימייל", "security.headers.update_password": "שנה סיסמא", "security.mfa": "הגדר אימות דו-גורמי", @@ -847,9 +847,9 @@ "soapbox_config.fields.brand_color_label": "צבע מותג", "soapbox_config.fields.crypto_address.add": "הוסף כתובת קריפטו חדשה", "soapbox_config.fields.crypto_addresses_label": "כתובות של מטבעות קריפטוגרפיים", - "soapbox_config.fields.home_footer.add": "Add new Home Footer Item", - "soapbox_config.fields.home_footer_fields_label": "Home footer items", - "soapbox_config.fields.logo_label": "Logo", + "soapbox_config.fields.home_footer.add": "הוסף פריט כותרת תחתונה חדש לבית", + "soapbox_config.fields.home_footer_fields_label": "פריטי כותרת תחתונה של הבית", + "soapbox_config.fields.logo_label": "לוגו", "soapbox_config.fields.promo_panel.add": "הוסף פריטי פאנל פרומו חדשים", "soapbox_config.fields.promo_panel_fields_label": "פריטי פאנל לפרומו", "soapbox_config.fields.theme_label": "ערכת נושא המוגדרת כברירת מחדל", @@ -893,70 +893,70 @@ "status.mute_conversation": "השתקת שיחה", "status.open": "הרחבת הודעה", "status.pin": "לקבע באודות", - "status.pinned": "Pinned post", - "status.reactions.cry": "Sad", - "status.reactions.empty": "No one has reacted to this post yet. When someone does, they will show up here.", - "status.reactions.heart": "Love", - "status.reactions.laughing": "Haha", - "status.reactions.like": "Like", - "status.reactions.open_mouth": "Wow", - "status.reactions.weary": "Weary", - "status.reactions_expand": "Select emoji", - "status.read_more": "Read more", + "status.pinned": "פוסט נעוץ", + "status.reactions.cry": "עצוב", + "status.reactions.empty": "אף אחד עדיין לא הגיב לפוסט הזה. כשמישהו יעשה זאת, הוא יופיע כאן.", + "status.reactions.heart": "אהבה", + "status.reactions.laughing": "חחח", + "status.reactions.like": "לייק", + "status.reactions.open_mouth": "ואו!", + "status.reactions.weary": "מיוגע", + "status.reactions_expand": "בחר אימוג'י", + "status.read_more": "קרא עוד", "status.reblog": "הדהוד", - "status.reblog_private": "Repost to original audience", + "status.reblog_private": "הדהוד לקהל המקורי", "status.reblogged_by": "הודהד על ידי {name}", - "status.reblogs.empty": "No one has reposted this post yet. When someone does, they will show up here.", - "status.redraft": "Delete & re-draft", - "status.remove_account_from_group": "Remove account from group", - "status.remove_post_from_group": "Remove post from group", + "status.reblogs.empty": "אף אחד עדיין לא פרסם מחדש את הפוסט הזה. כשמישהו יעשה זאת, הוא יופיע כאן.", + "status.redraft": "מחק וכתוב מחדש", + "status.remove_account_from_group": "הסר חשבון מהקבוצה", + "status.remove_post_from_group": "הסר פוסט מהקבוצה", "status.reply": "תגובה", "status.replyAll": "תגובה לכולם", "status.report": "דיווח על @{name}", "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_thread": "Show thread", - "status.title": "Post", - "status.title_direct": "Direct message", - "status.unbookmark": "Remove bookmark", - "status.unbookmarked": "Bookmark removed.", + "status.show_more_all": "הראה יותר לכולם", + "status.show_thread": "הצג שרשור", + "status.title": "פוסט", + "status.title_direct": "הודעה ישירה", + "status.unbookmark": "הסר סימניה", + "status.unbookmarked": "סימניה הוסרה.", "status.unmute_conversation": "הסרת השתקת שיחה", "status.unpin": "לשחרר מקיבוע באודות", - "status_list.queue_label": "Click to see {count} new {count, plural, one {post} other {posts}}", - "statuses.tombstone": "One or more posts is unavailable.", - "suggestions.dismiss": "Dismiss suggestion", - "tabs_bar.all": "All", - "tabs_bar.apps": "Apps", - "tabs_bar.chats": "Chats", - "tabs_bar.dashboard": "Dashboard", - "tabs_bar.fediverse": "Fediverse", - "tabs_bar.header": "Account Info", - "tabs_bar.home": "בבית", - "tabs_bar.news": "News", + "status_list.queue_label": "לחץ כדי לראות {count} חדשים {count, plural, one {פוסט} other {פוסטים}}", + "statuses.tombstone": "פוסט אחד או יותר אינו זמין.", + "suggestions.dismiss": "דחה את ההצעה", + "tabs_bar.all": "הכל", + "tabs_bar.apps": "אפליקציות", + "tabs_bar.chats": "צ'אטים", + "tabs_bar.dashboard": "לוח מחוונים", + "tabs_bar.fediverse": "פדרציה", + "tabs_bar.header": "פרטי חשבון", + "tabs_bar.home": "בית", + "tabs_bar.news": "חדשות", "tabs_bar.notifications": "התראות", - "tabs_bar.post": "Post", - "tabs_bar.search": "Search", - "tabs_bar.theme_toggle_dark": "Switch to dark theme", - "tabs_bar.theme_toggle_light": "Switch to light theme", - "time_remaining.days": "{number, plural, one {# day} other {# days}} left", - "time_remaining.hours": "{number, plural, one {# hour} other {# hours}} left", - "time_remaining.minutes": "{number, plural, one {# minute} other {# minutes}} left", - "time_remaining.moments": "Moments remaining", - "time_remaining.seconds": "{number, plural, one {# second} other {# seconds}} left", - "trends.count_by_accounts": "{count} {rawCount, plural, one {person} other {people}} talking", - "trends.title": "Trends", - "ui.beforeunload": "הטיוטא תאבד אם תעזבו את מסטודון.", - "unauthorized_modal.footer": "Already have an account? {login}.", - "unauthorized_modal.text": "You need to be logged in to do that.", - "unauthorized_modal.title": "Sign up for {site_title}", + "tabs_bar.post": "פוסט", + "tabs_bar.search": "חיפוש", + "tabs_bar.theme_toggle_dark": "עבור לערכת נושא כהה", + "tabs_bar.theme_toggle_light": "עבור לערכת נושא בהירה", + "time_remaining.days": "{number, plural, one {# יום} other {# ימים}} נותרו", + "time_remaining.hours": "{number, plural, one {# שעה} other {# שעות}} נותרו", + "time_remaining.minutes": "{number, plural, one {# דקה} other {# דקות}} נותרו", + "time_remaining.moments": "נותרו רגעים", + "time_remaining.seconds": "{number, plural, one {# שנייה} other {# שניות}} נותרו", + "trends.count_by_accounts": "{count} {rawCount, plural, one {אדם} other {אנשים}} מדברים", + "trends.title": "טרנדים", + "ui.beforeunload": "הטיוטא תאבד אם תעזבו את סבוניה.", + "unauthorized_modal.footer": "כבר יש לך חשבון? {login}.", + "unauthorized_modal.text": "אתה צריך להיות מחובר כדי לעשות זאת.", + "unauthorized_modal.title": "להירשם ל{site_title}", "upload_area.title": "ניתן להעלות על ידי Drag & drop", "upload_button.label": "הוספת מדיה", - "upload_error.limit": "File upload limit exceeded.", - "upload_error.poll": "File upload not allowed with polls.", + "upload_error.limit": "חרגת ממגבלת העלאת הקבצים.", + "upload_error.poll": "העלאת קבצים אסורה ביחד עם סקרים.", "upload_form.description": "תיאור לכבדי ראיה", "upload_form.preview": "תצוגה מקדימה", "upload_form.undo": "ביטול", From a6d34af6e48820809bb22f4e1ca0976cf4f0fcd2 Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 01:58:12 +0000 Subject: [PATCH 09/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 47d76c275..48a70660e 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -73,7 +73,7 @@ "admin.dashcounters.user_count_label": "סך כל המשתמשים", "admin.dashwidgets.email_list_header": "רשימת אימייל", "admin.dashwidgets.software_header": "תוכנה", - "admin.latest_accounts_panel.expand_message": "לחץ כדי לראות {count} עוד{count, plural, one {account} other {accounts}}", + "admin.latest_accounts_panel.expand_message": "לחץ כדי לראות {count} עוד{count, plural, one {חשבון} other {חשבונות}}", "admin.latest_accounts_panel.title": "חשבונות אחרונים", "admin.moderation_log.empty_message": "לא ביצעת פעולות ניהול עדיין. כשתבצע, ההיסטוריה תהיה כאן.", "admin.reports.actions.close": "סגור", From c3e7c8e1dde4ebb027530f67c89a202bc1c3b381 Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 02:03:28 +0000 Subject: [PATCH 10/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 48a70660e..e56563fea 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -305,8 +305,9 @@ "confirmations.unfollow.confirm": "להפסיק מעקב", "confirmations.unfollow.message": "להפסיק מעקב אחרי {name}?", "crypto_donate.explanation_box.message": "{siteTitle} מקבל תרומות של מטבעות קריפטוגרפיים. ניתן לשלוח תרומה לכל אחת מהכתובות למטה. תודה על תמיכתך!", + "crypto_donate.explanation_box.title": "שליחת תרומות מטבעות קריפטוגרפיים", - "crypto_donate_panel.actions.more": "לחץ כדי לראות {count} ועוד {count, plural, one {wallet} other {wallets}}", + "crypto_donate_panel.actions.more": "לחץ כדי לראות {count} עוד {count, plural, one {ארנק} other {ארנקים}}", "crypto_donate_panel.heading": "תרום מטבעות קריפטו", "crypto_donate_panel.intro.message": "{siteTitle} מקבל תרומות של מטבעות קריפטוגרפיים כדי לממן את השירות שלנו. תודה על תמיכתך!", "datepicker.hint": "מתוכנן לפרסם ב...", @@ -350,7 +351,7 @@ "edit_profile.hints.header": "PNG, GIF או JPG. יוקטן ל-{size}", "edit_profile.hints.hide_network": "מי אתה עוקב ומי עוקב אחריך לא יוצג בפרופיל שלך", "edit_profile.hints.locked": "מחייב אותך לאשר עוקבים באופן ידני", - "edit_profile.hints.meta_fields": "תוכל להציג עד {count, plural, one {# item} other {# items}} אחרים כטבלה בפרופיל שלך", + "edit_profile.hints.meta_fields": "תוכל להציג עד {count, plural, one {# פריט} other {# פריטים}} אחרים כטבלה בפרופיל שלך", "edit_profile.hints.stranger_notifications": "הצג רק התראות מאנשים שאתה עוקב אחריהם", "edit_profile.meta_fields.add": "הוסף פריט חדש", "edit_profile.save": "שמירה", @@ -504,9 +505,9 @@ "import_data.success.blocks": "חסימות יובאו בהצלחה", "import_data.success.followers": "מעקבים יובאו בהצלחה", "import_data.success.mutes": "השתקות יובאו בהצלחה", - "intervals.full.days": "{number, plural, one {# day} other {# days}}", - "intervals.full.hours": "{number, plural, one {# hour} other {# hours}}", - "intervals.full.minutes": "{number, plural, one {# minute} other {# minutes}}", + "intervals.full.days": "{number, plural, one {# יום} other {# ימים}}", + "intervals.full.hours": "{number, plural, one {# שעה} other {# שעות}}", + "intervals.full.minutes": "{number, plural, one {# דקה} other {# דקות}}", "introduction.federation.action": "הבא", "introduction.federation.home.headline": "בית", "introduction.federation.home.text": "פוסטים מאנשים שאתה עוקב אחריהם יופיעו בפיד הביתי שלך. אתה יכול לעקוב אחר כל אחד בכל שרת!", @@ -598,8 +599,8 @@ "missing_description_modal.text": "לא הזנת תיאור עבור כל הקבצים המצורפים. המשך בכל זאת?", "missing_indicator.label": "לא נמצא", "missing_indicator.sublabel": "משאב זה לא נמצא", - "morefollows.followers_label": "ו-{count} עוד {count, plural, one {follower} other {followers}} באתרים מרוחקים.", - "morefollows.following_label": "ו-{count} עוד {count, plural, one {follow} other {follows}} באתרים מרוחקים.", + "morefollows.followers_label": "ו-{count} עוד {count, plural, one {עוקב} other {עוקבים}} באתרים מרוחקים.", + "morefollows.following_label": "ו-{count} עוד {count, plural, one {מעקב} other {מעקבים}} באתרים מרוחקים.", "mute_modal.hide_notifications": "להסתיר הודעות מחשבון זה?", "navigation.chats": "צ'אטים", "navigation.dashboard": "לוח מחוונים", From 4928024e9a199150f3916241fd1cb11755805833 Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 02:33:29 +0000 Subject: [PATCH 11/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index e56563fea..4e790aa67 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -610,7 +610,7 @@ "navigation.invites": "הזמנות", "navigation.notifications": "התראות", "navigation.search": "חיפוש", - "navigation_bar.account_aliases": "כיונויי חשבון", + "navigation_bar.account_aliases": "כיוניי חשבון", "navigation_bar.admin_settings": "הגדרות אדמין", "navigation_bar.blocks": "חסימות", "navigation_bar.bookmarks": "סימניות", From 39c9161bfb0a588b34b0bcd80422fc5ad16cc15c Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 02:36:50 +0000 Subject: [PATCH 12/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 4e790aa67..d37073c02 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -260,7 +260,7 @@ "compose_form.poll.switch_to_multiple": "שנה סקר כדי לאפשר אפשרויות בחירה מרובות", "compose_form.poll.switch_to_single": "שנה סקר כדי לאפשר בחירה יחידה", "compose_form.publish": "ללחוש", - "compose_form.publish_loud": "פרסם!", + "compose_form.publish_loud": "!פרסם", "compose_form.schedule": "לתזמן", "compose_form.scheduled_statuses.click_here": "לחץ כאן", "compose_form.scheduled_statuses.message": "יש לך פוסטים מתוזמנים. {לחץ_כאן} כדי לראות אותם.", From fb7c642dc7f7ce0a1d7e9ce3b9f5b7ca3641e61d Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Sun, 6 Feb 2022 20:46:06 -0600 Subject: [PATCH 13/30] GoToSocial support --- app/soapbox/actions/instance.js | 1 + app/soapbox/components/avatar.js | 24 ++++++++++++++++-------- app/soapbox/utils/features.js | 21 ++++++++++++++++----- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/app/soapbox/actions/instance.js b/app/soapbox/actions/instance.js index 85d8b2a3f..b1df09d64 100644 --- a/app/soapbox/actions/instance.js +++ b/app/soapbox/actions/instance.js @@ -61,6 +61,7 @@ export function fetchInstance() { dispatch(fetchNodeinfo()); // Pleroma < 2.1 backwards compatibility } }).catch(error => { + console.error(error); dispatch({ type: INSTANCE_FETCH_FAIL, error, skipAlert: true }); }); }; diff --git a/app/soapbox/components/avatar.js b/app/soapbox/components/avatar.js index 1bbca72cc..d0df7959b 100644 --- a/app/soapbox/components/avatar.js +++ b/app/soapbox/components/avatar.js @@ -28,14 +28,22 @@ export default class Avatar extends React.PureComponent { height: `${size}px`, }; - return ( - - ); + // Only render the image if src is provided + if (account.get('avatar')) { + return ( + + ); + } else { + // Fall back on rendering an empty div + return ( +
+ ); + } } } diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js index 6df42d1e7..e55ca455c 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.js @@ -89,9 +89,20 @@ export const getFeatures = createSelector([ export const parseVersion = version => { const regex = /^([\w\.]*)(?: \(compatible; ([\w]*) (.*)\))?$/; const match = regex.exec(version); - return { - software: match[2] || MASTODON, - version: match[3] || match[1], - compatVersion: match[1], - }; + + if (match) { + return { + software: match[2] || MASTODON, + version: match[3] || match[1], + compatVersion: match[1], + }; + } else { + // If we can't parse the version, this is a new and exotic backend. + // Fall back to minimal featureset. + return { + software: null, + version: '0.0.0', + compatVersion: '0.0.0', + }; + } }; From 387690d46a71325a5804ba9f659acee0c799accf Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 02:46:46 +0000 Subject: [PATCH 14/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index d37073c02..0d4ed9104 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -755,11 +755,11 @@ "registration.sign_up": "הירשם", "registration.tos": "תנאי השירות", "registration.username_unavailable": "שם המשתמש תפוס.", - "relative_time.days": "{number}d", - "relative_time.hours": "{number}h", + "relative_time.days": "ימים {number}", + "relative_time.hours": "שעות {number}", "relative_time.just_now": "כרגע", - "relative_time.minutes": "{number}m", - "relative_time.seconds": "{number}s", + "relative_time.minutes": "דקות {number}", + "relative_time.seconds": "שניות {number}", "remote_instance.edit_federation": "ערוך פדרציה", "remote_instance.federation_panel.heading": "הגבלות הפדרציה", "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} לא הטיל הגבלות על {host}.", From a50ca998c26e24cff0ab41a383f92c74ca10515e Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 03:01:45 +0000 Subject: [PATCH 15/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index 0d4ed9104..faa0239b0 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -336,6 +336,7 @@ "edit_profile.fields.discoverable_label": "אפשר גילוי חשבון", "edit_profile.fields.display_name_label": "שם תצוגה", "edit_profile.fields.display_name_placeholder": "שם", + "edit_profile.fields.birthday_placeholder": "יום הולדת", "edit_profile.fields.header_label": "כותרת", "edit_profile.fields.hide_network_label": "הסתר רשת", "edit_profile.fields.locked_label": "נעל חשבון", From 70d59e06733861e0d53c455cb738fea193f2b67e Mon Sep 17 00:00:00 2001 From: Ashdemai Date: Mon, 7 Feb 2022 03:03:52 +0000 Subject: [PATCH 16/30] Update app/soapbox/locales/he.json --- app/soapbox/locales/he.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/soapbox/locales/he.json b/app/soapbox/locales/he.json index faa0239b0..a454c56de 100644 --- a/app/soapbox/locales/he.json +++ b/app/soapbox/locales/he.json @@ -336,7 +336,8 @@ "edit_profile.fields.discoverable_label": "אפשר גילוי חשבון", "edit_profile.fields.display_name_label": "שם תצוגה", "edit_profile.fields.display_name_placeholder": "שם", - "edit_profile.fields.birthday_placeholder": "יום הולדת", + "edit_profile.fields.birthday_label": "יום הולדת", + "edit_profile.fields.birthday_placeholder": "תאריך הלידה שלך", "edit_profile.fields.header_label": "כותרת", "edit_profile.fields.hide_network_label": "הסתר רשת", "edit_profile.fields.locked_label": "נעל חשבון", From 69712baa02726dde1c0bd3349cbd163a7683a64e Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 11:50:05 -0600 Subject: [PATCH 17/30] Normalizer: normalize required account & status fields --- app/soapbox/actions/importer/normalizer.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/soapbox/actions/importer/normalizer.js b/app/soapbox/actions/importer/normalizer.js index 66524b556..0f3f2da6e 100644 --- a/app/soapbox/actions/importer/normalizer.js +++ b/app/soapbox/actions/importer/normalizer.js @@ -15,6 +15,11 @@ const makeEmojiMap = record => record.emojis.reduce((obj, emoji) => { export function normalizeAccount(account) { account = { ...account }; + // Some backends can return null, or omit these required fields + if (!account.emojis) account.emojis = []; + if (!account.display_name) account.display_name = ''; + if (!account.note) account.note = ''; + const emojiMap = makeEmojiMap(account); const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name; @@ -41,6 +46,10 @@ export function normalizeAccount(account) { export function normalizeStatus(status, normalOldStatus, expandSpoilers) { const normalStatus = { ...status }; + // Some backends can return null, or omit these required fields + if (!normalStatus.emojis) normalStatus.emojis = []; + if (!normalStatus.spoiler_text) normalStatus.spoiler_text = ''; + // Copy the pleroma object too, so we can modify our copy if (status.pleroma) { normalStatus.pleroma = { ...status.pleroma }; From c084a7a232a4a8df2913fe126c39b1feb9ea854b Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 12:19:28 -0600 Subject: [PATCH 18/30] Mitra: handle status context endpoint as a list of statuses --- app/soapbox/__fixtures__/mitra-context.json | 107 ++++++++++++++++++ .../actions/__tests__/statuses-test.js | 29 +++++ app/soapbox/actions/statuses.js | 16 ++- 3 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 app/soapbox/__fixtures__/mitra-context.json create mode 100644 app/soapbox/actions/__tests__/statuses-test.js diff --git a/app/soapbox/__fixtures__/mitra-context.json b/app/soapbox/__fixtures__/mitra-context.json new file mode 100644 index 000000000..91b48420c --- /dev/null +++ b/app/soapbox/__fixtures__/mitra-context.json @@ -0,0 +1,107 @@ +[ + { + "id": "017ed503-bc96-301a-e871-2c23b30ddd05", + "uri": "https://mitra.social/objects/017ed503-bc96-301a-e871-2c23b30ddd05", + "created_at": "2022-02-07T16:28:18.966874Z", + "account": { + "id": "017ed4f9-c121-2ae6-0805-15516cce02c3", + "username": "alex", + "acct": "alex", + "url": "https://mitra.social/users/alex", + "display_name": null, + "created_at": "2022-02-07T16:17:24.769229Z", + "note": null, + "avatar": null, + "header": null, + "fields": [], + "followers_count": 1, + "following_count": 1, + "statuses_count": 3, + "source": null, + "wallet_address": null + }, + "content": "@silverpill sup!", + "in_reply_to_id": null, + "reblog": null, + "visibility": "public", + "replies_count": 1, + "favourites_count": 0, + "reblogs_count": 0, + "media_attachments": [], + "mentions": [ + { + "id": "dd4ebc18-269d-4c7b-a310-03d29c6ab551", + "username": "silverpill", + "acct": "silverpill", + "url": "https://mitra.social/users/silverpill" + } + ], + "tags": [], + "favourited": false, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null + }, + { + "id": "017ed505-5926-392f-256a-f86d5075df70", + "uri": "https://mitra.social/objects/017ed505-5926-392f-256a-f86d5075df70", + "created_at": "2022-02-07T16:30:04.582771Z", + "account": { + "id": "dd4ebc18-269d-4c7b-a310-03d29c6ab551", + "username": "silverpill", + "acct": "silverpill", + "url": "https://mitra.social/users/silverpill", + "display_name": "silverpill", + "created_at": "2021-11-06T21:08:57.441927Z", + "note": "Admin of mitra.social instance. It is running experimental ActivityPub server Mitra.", + "avatar": "https://mitra.social/media/6a785bf7dd05f61c3590e8935aa49156a499ac30fd1e402f79e7e164adb36e2c.png", + "header": null, + "fields": [ + { + "name": "Matrix", + "value": "@silverpill:poa.st" + }, + { + "name": "Alt", + "value": "@silverpill@poa.st" + }, + { + "name": "Code", + "value": "https://codeberg.org/silverpill/" + }, + { + "name": "$XMR", + "value": "884y9LmsWY7PQNsyR7bJy1dvj91tuF5spVabyCnPk4KfQtSuzFbQobTFC7xSemJgVW1FWAwnJbjTZX5zZWbBrfkv62DB62d" + } + ], + "followers_count": 27, + "following_count": 15, + "statuses_count": 110, + "source": null, + "wallet_address": null + }, + "content": "@alex welcome", + "in_reply_to_id": "017ed503-bc96-301a-e871-2c23b30ddd05", + "reblog": null, + "visibility": "public", + "replies_count": 0, + "favourites_count": 1, + "reblogs_count": 0, + "media_attachments": [], + "mentions": [ + { + "id": "017ed4f9-c121-2ae6-0805-15516cce02c3", + "username": "alex", + "acct": "alex", + "url": "https://mitra.social/users/alex" + } + ], + "tags": [], + "favourited": true, + "reblogged": false, + "ipfs_cid": null, + "token_id": null, + "token_tx_id": null + } +] diff --git a/app/soapbox/actions/__tests__/statuses-test.js b/app/soapbox/actions/__tests__/statuses-test.js new file mode 100644 index 000000000..71a0596a4 --- /dev/null +++ b/app/soapbox/actions/__tests__/statuses-test.js @@ -0,0 +1,29 @@ +import { Map as ImmutableMap } from 'immutable'; + +import { STATUSES_IMPORT } from 'soapbox/actions/importer'; +import { __stub } from 'soapbox/api'; +import { mockStore } from 'soapbox/test_helpers'; + +import { fetchContext } from '../statuses'; + +describe('fetchContext()', () => { + it('handles Mitra context', done => { + const statuses = require('soapbox/__fixtures__/mitra-context.json'); + + __stub(mock => { + mock.onGet('/api/v1/statuses/017ed505-5926-392f-256a-f86d5075df70/context') + .reply(200, statuses); + }); + + const store = mockStore(ImmutableMap()); + + store.dispatch(fetchContext('017ed505-5926-392f-256a-f86d5075df70')).then(context => { + const actions = store.getActions(); + + expect(actions[3].type).toEqual(STATUSES_IMPORT); + expect(actions[3].statuses[0].id).toEqual('017ed503-bc96-301a-e871-2c23b30ddd05'); + + done(); + }).catch(console.error); + }); +}); diff --git a/app/soapbox/actions/statuses.js b/app/soapbox/actions/statuses.js index 150b6d8c7..12dfaa576 100644 --- a/app/soapbox/actions/statuses.js +++ b/app/soapbox/actions/statuses.js @@ -143,10 +143,18 @@ export function fetchContext(id) { dispatch({ type: CONTEXT_FETCH_REQUEST, id }); return api(getState).get(`/api/v1/statuses/${id}/context`).then(({ data: context }) => { - const { ancestors, descendants } = context; - const statuses = ancestors.concat(descendants); - dispatch(importFetchedStatuses(statuses)); - dispatch({ type: CONTEXT_FETCH_SUCCESS, id, ancestors, descendants }); + if (Array.isArray(context)) { + // Mitra: returns a list of statuses + dispatch(importFetchedStatuses(context)); + } else if (typeof context === 'object') { + // Standard Mastodon API returns a map with `ancestors` and `descendants` + const { ancestors, descendants } = context; + const statuses = ancestors.concat(descendants); + dispatch(importFetchedStatuses(statuses)); + dispatch({ type: CONTEXT_FETCH_SUCCESS, id, ancestors, descendants }); + } else { + throw context; + } return context; }).catch(error => { if (error.response && error.response.status === 404) { From 2c51054ae4189e98336c7fad77f047301b2b8852 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 12:20:03 -0600 Subject: [PATCH 19/30] UI: actually, don't wait for the streaming URL to render --- app/soapbox/features/ui/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index bfcfdb3cd..1e0ed2d51 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -670,14 +670,12 @@ class UI extends React.PureComponent { } render() { - const { streamingUrl, features, soapbox } = this.props; + const { features, soapbox } = this.props; const { draggingOver, mobile } = this.state; const { intl, children, location, dropdownMenuIsOpen, me } = this.props; // Wait for login to succeed or fail if (me === null) return null; - // If login didn't fail, wait for streaming to become available - if (me !== false && !streamingUrl) return null; const handlers = me ? { help: this.handleHotkeyToggleHelp, From c4bf347daebcd8d61ea7023ef2ee77ff9c0dfc03 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 12:26:11 -0600 Subject: [PATCH 20/30] MediaGallery: fall back on `url` when `preview_url` isn't provided --- app/soapbox/components/media_gallery.js | 2 +- app/soapbox/features/account_gallery/components/media_item.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/soapbox/components/media_gallery.js b/app/soapbox/components/media_gallery.js index bad4c1b48..34c79c140 100644 --- a/app/soapbox/components/media_gallery.js +++ b/app/soapbox/components/media_gallery.js @@ -168,7 +168,7 @@ class Item extends React.PureComponent { onClick={this.handleClick} target='_blank' > - + ); } else if (attachment.get('type') === 'gifv') { diff --git a/app/soapbox/features/account_gallery/components/media_item.js b/app/soapbox/features/account_gallery/components/media_item.js index 1cccfe070..0c5b0afdb 100644 --- a/app/soapbox/features/account_gallery/components/media_item.js +++ b/app/soapbox/features/account_gallery/components/media_item.js @@ -88,7 +88,7 @@ class MediaItem extends ImmutablePureComponent { thumbnail = ( From d260cc2e2c3bd241c74f3be1e25c9015bb7f676c Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Mon, 7 Feb 2022 13:06:20 -0600 Subject: [PATCH 21/30] Add fallback avatar --- app/images/avatar-missing.png | Bin 0 -> 14800 bytes app/images/avatar-missing.svg | 116 +++++++++++++++++++++ app/soapbox/actions/importer/normalizer.js | 2 + app/soapbox/components/avatar.js | 24 ++--- 4 files changed, 126 insertions(+), 16 deletions(-) create mode 100644 app/images/avatar-missing.png create mode 100644 app/images/avatar-missing.svg diff --git a/app/images/avatar-missing.png b/app/images/avatar-missing.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e6b5709c611c8b26d18d3c55bac315ae46b176 GIT binary patch literal 14800 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 aV(i#=ulV2_$bplZAXzCT$!ZB`(0>E8Zt?m6 literal 0 HcmV?d00001 diff --git a/app/images/avatar-missing.svg b/app/images/avatar-missing.svg new file mode 100644 index 000000000..7eb156089 --- /dev/null +++ b/app/images/avatar-missing.svg @@ -0,0 +1,116 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/soapbox/actions/importer/normalizer.js b/app/soapbox/actions/importer/normalizer.js index 0f3f2da6e..7c5aa8bd3 100644 --- a/app/soapbox/actions/importer/normalizer.js +++ b/app/soapbox/actions/importer/normalizer.js @@ -19,6 +19,8 @@ export function normalizeAccount(account) { if (!account.emojis) account.emojis = []; if (!account.display_name) account.display_name = ''; if (!account.note) account.note = ''; + if (!account.avatar) account.avatar = account.avatar_static || require('images/avatar-missing.png'); + if (!account.avatar_static) account.avatar_static = account.avatar; const emojiMap = makeEmojiMap(account); const displayName = account.display_name.trim().length === 0 ? account.username : account.display_name; diff --git a/app/soapbox/components/avatar.js b/app/soapbox/components/avatar.js index d0df7959b..1bbca72cc 100644 --- a/app/soapbox/components/avatar.js +++ b/app/soapbox/components/avatar.js @@ -28,22 +28,14 @@ export default class Avatar extends React.PureComponent { height: `${size}px`, }; - // Only render the image if src is provided - if (account.get('avatar')) { - return ( - - ); - } else { - // Fall back on rendering an empty div - return ( -
- ); - } + return ( + + ); } } From 6687741057f6c27f53ec759dbfb50c983186da66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Wed, 9 Feb 2022 12:58:28 +0100 Subject: [PATCH 22/30] Update Polish translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/locales/pl.json | 117 +++++++++++++++++++----------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/app/soapbox/locales/pl.json b/app/soapbox/locales/pl.json index e3ebca24d..470bac41b 100644 --- a/app/soapbox/locales/pl.json +++ b/app/soapbox/locales/pl.json @@ -4,12 +4,12 @@ "accordion.expand": "Rozwiń", "account.add_or_remove_from_list": "Dodaj lub usuń z list", "account.badges.bot": "Bot", + "account.birthday": "Urodzony(-a) {date}", + "account.birthday_today": "Ma dziś urodziny!", "account.block": "Blokuj @{name}", "account.block_domain": "Blokuj wszystko z {domain}", "account.blocked": "Zablokowany(-a)", "account.chat": "Napisz do @{name}", - "account.column_settings.description": "Te ustawienia stosowane są do osi czasu wszystkich kont.", - "account.column_settings.title": "Ustawienia osi czasu konta", "account.deactivated": "Dezaktywowany(-a)", "account.deactivated_description": "To konto zostało zdezaktywowane.", "account.direct": "Wyślij wiadomość bezpośrednią do @{name}", @@ -45,8 +45,8 @@ "account.share": "Udostępnij profil @{name}", "account.show_reblogs": "Pokazuj podbicia od @{name}", "account.subscribe": "Subskrybuj wpisy @{name}", - "account.subscribed": "Subscribed", - "account.unblock": "Zasubskrybowano", + "account.subscribed": "Subskrybujesz", + "account.unblock": "Odblokuj @{name}", "account.unblock_domain": "Odblokuj domenę {domain}", "account.unendorse": "Przestań polecać", "account.unfollow": "Przestań śledzić", @@ -54,7 +54,6 @@ "account.unsubscribe": "Przestań subskrybować wpisy @{name}", "account_gallery.none": "Brak zawartości multimedialnej do wyświetlenia.", "account_search.placeholder": "Szukaj konta", - "account_timeline.column_settings.show_pinned": "Pokazuj przypięte wpisy", "admin.awaiting_approval.approved_message": "Przyjęto {acct}!", "admin.awaiting_approval.empty_message": "Nikt nie oczekuje przyjęcia. Gdy zarejestruje się nowy użytkownik, możesz zatwierdzić go tutaj.", "admin.awaiting_approval.rejected_message": "Odrzucono {acct}!", @@ -148,7 +147,6 @@ "bundle_modal_error.close": "Zamknij", "bundle_modal_error.message": "Coś poszło nie tak podczas ładowania tego składnika.", "bundle_modal_error.retry": "Spróbuj ponownie", - "chat_box.actions.close": "Zamknij czat", "chat_box.actions.send": "Wyślij", "chat_box.input.placeholder": "Wyślij wiadomość…", "chat_panels.main_window.empty": "Nie znaleziono rozmów. Aby zacząć rozmowę, odwiedź profil użytkownika.", @@ -176,6 +174,7 @@ "column.aliases.subheading_aliases": "Istniejące aliasy", "column.app_create": "Utwórz aplikację", "column.backups": "Kopie zapasowe", + "column.birthdays": "Urodziny", "column.blocks": "Zablokowani użytkownicy", "column.bookmarks": "Zakładki", "column.chats": "Rozmowy", @@ -234,11 +233,11 @@ "column.scheduled_statuses": "Zaplanowane wpisy", "column.search": "Szukaj", "column.security": "Bezpieczeństwo", + "column.settings_store": "Settings store", "column.soapbox_config": "Konfiguracja Soapbox", "column_back_button.label": "Wróć", "column_forbidden.body": "Nie masz uprawnień, aby odwiedzić tę stronę.", "column_forbidden.title": "Niedozwolone", - "column_header.hide_settings": "Ukryj ustawienia", "column_header.show_settings": "Pokaż ustawienia", "community.column_settings.media_only": "Tylko zawartość multimedialna", "community.column_settings.title": "Ustawienia lokalnej osi czasu", @@ -272,40 +271,54 @@ "compose_form.spoiler_placeholder": "Wprowadź swoje ostrzeżenie o zawartości", "confirmation_modal.cancel": "Anuluj", "confirmations.admin.deactivate_user.confirm": "Dezaktywuj @{name}", + "confirmations.admin.deactivate_user.heading": "Dezaktywuj @{acct}", "confirmations.admin.deactivate_user.message": "Zamierzasz zdezaktywować @{acct}. Dezaktywacja konta może zostać cofnięta.", "confirmations.admin.delete_local_user.checkbox": "Wiem, że właśnie usuwam lokalnego użytkownika.", "confirmations.admin.delete_status.confirm": "Usuń wpis", + "confirmations.admin.delete_status.heading": "Usuń wpis", "confirmations.admin.delete_status.message": "Zamierzasz usunąć wpis użytkownika @{acct}. To działanie nie może zostać cofnięte.", "confirmations.admin.delete_user.confirm": "Usuń @{name}", + "confirmations.admin.delete_user.heading": "Usuń @{acct}", "confirmations.admin.delete_user.message": "Zamierzasz usunąć @{acct}. TO DZIAŁANIE NIE MOŻE ZOSTAĆ COFNIĘTE.", "confirmations.admin.mark_status_not_sensitive.confirm": "Oznacz wpis jako niewrażliwy", + "confirmations.admin.mark_status_not_sensitive.heading": "Oznacz wpis jako niewrażliwy.", "confirmations.admin.mark_status_not_sensitive.message": "Zamierzasz oznaczyć wpis {acct} jako niewrażliwy.", "confirmations.admin.mark_status_sensitive.confirm": "Oznacz wpis jako wrażliwy", + "confirmations.admin.mark_status_sensitive.heading": "Oznacz wpis jako wrażliwy", "confirmations.admin.mark_status_sensitive.message": "Zamierzasz oznaczyć wpis {acct} jako wrażliwy.", "confirmations.admin.reject_user.confirm": "Odrzuć @{name}", + "confirmations.admin.reject_user.heading": "Odrzuć @{acct}", "confirmations.admin.reject_user.message": "Zamierzasz odrzucić prośbę o rejestrację @{acct}. To działanie nie może zostać cofnięte.", "confirmations.block.block_and_report": "Zablokuj i zgłoś", "confirmations.block.confirm": "Zablokuj", + "confirmations.block.heading": "Zablokuj @{name}", "confirmations.block.message": "Czy na pewno chcesz zablokować {name}?", "confirmations.delete.confirm": "Usuń", "confirmations.delete.heading": "Usuń wpis", "confirmations.delete.message": "Czy na pewno chcesz usunąć ten wpis?", "confirmations.delete_list.confirm": "Usuń", + "confirmations.delete_list.heading": "Usuń listę", "confirmations.delete_list.message": "Czy na pewno chcesz bezpowrotnie usunąć tą listę?", "confirmations.domain_block.confirm": "Ukryj wszysyko z domeny", + "confirmations.domain_block.heading": "Zablokuj {domain}", "confirmations.domain_block.message": "Czy na pewno chcesz zablokować całą domenę {domain}? Zwykle lepszym rozwiązaniem jest blokada lub wyciszenie kilku użytkowników.", "confirmations.mute.confirm": "Wycisz", + "confirmations.mute.heading": "Wycisz @{name}", "confirmations.mute.message": "Czy na pewno chcesz wyciszyć {name}?", "confirmations.redraft.confirm": "Usuń i przeredaguj", + "confirmations.redraft.heading": "Usuń i przeredaguj", "confirmations.redraft.message": "Czy na pewno chcesz usunąć i przeredagować ten wpis? Polubienia i podbicia zostaną utracone, a odpowiedzi do oryginalnego wpisu zostaną osierocone.", "confirmations.register.needs_approval": "Twoje konto musi zostać ręcznie zatwierdzone przez administratora. Zachowaj cierpliwość, a my sprawdzimy szczegóły Twojej rejestracji.", + "confirmations.register.needs_approval.header": "Wymagane zatwierdzenie", "confirmations.register.needs_confirmation": "Sprawdź swoją skrzynkę na {email}, aby znaleźć instrukcje potwierdzania. Musisz zweryfikować swój adres e-mail, aby kontynuować.", + "confirmations.register.needs_confirmation.header": "Wymagane potwierdzenie", "confirmations.reply.confirm": "Odpowiedz", "confirmations.reply.message": "W ten sposób utracisz wpis który obecnie tworzysz. Czy na pewno chcesz to zrobić?", "confirmations.scheduled_status_delete.confirm": "Anuluj", "confirmations.scheduled_status_delete.heading": "Anuluj zaplanowany wpis", "confirmations.scheduled_status_delete.message": "Czy na pewno chcesz anulować ten zaplanowany wpis?", "confirmations.unfollow.confirm": "Przestań śledzić", + "confirmations.unfollow.heading": "Przestań śledzić {name}", "confirmations.unfollow.message": "Czy na pewno zamierzasz przestać śledzić {name}?", "crypto_donate.explanation_box.message": "{siteTitle} przyjmuje darowizny w kryptowalutach. Możesz wysłać darowiznę na jeden z poniższych adresów. Dziękujemy za Wasze wsparcie!", "crypto_donate.explanation_box.title": "Przekaż darowiznę w kryptowalutach", @@ -313,8 +326,22 @@ "crypto_donate_panel.heading": "Przekaż kryptowalutę", "crypto_donate_panel.intro.message": "{siteTitle} przyjmuje darowizny w kryptowalutach, aby utrzymać naszą usługę. Dziękujemy za Wasze wsparcie!", "datepicker.hint": "Zaplanowano publikację na…", + "datepicker.next_month": "Następny miesiąc", + "datepicker.next_year": "Następny rok", + "datepicker.previous_month": "Poprzedni miesiąc", + "datepicker.previous_year": "Poprzedni rok", + "developers.challenge.answer_label": "Odpowiedź", + "developers.challenge.answer_placeholder": "Twoja odpowiedź", + "developers.challenge.fail": "Nieprawidłowa odpowiedź", + "developers.challenge.message": "Jaki jest wynik wywołania {function}?", + "developers.challenge.submit": "Zostań programistą", + "developers.challenge.success": "Jesteś teraz programistą", + "developers.leave": "Nie jesteś już programistą", "developers.navigation.app_create_label": "Utwórz aplikację", "developers.navigation.intentional_error_label": "Wywołaj błąd", + "developers.navigation.leave_developers_label": "Opuść programistów", + "developers.navigation.settings_store_label": "Settings store", + "developers.settings_store.hint": "Możesz tu bezpośrednio edytować swoje ustawienia. UWAŻAJ! Edytowanie tej sekcji może uszkodzić Twoje konto, co może zostać naprawione tylko przez API.", "direct.search_placeholder": "Wyślij wiadomość do…", "directory.federated": "Z całego znanego Fediwersum", "directory.local": "Tylko z {domain}", @@ -334,6 +361,8 @@ "edit_profile.fields.avatar_label": "Awatar", "edit_profile.fields.bio_label": "Opis", "edit_profile.fields.bio_placeholder": "Powiedz nam coś o sobie.", + "edit_profile.fields.birthday_label": "Urodziny", + "edit_profile.fields.birthday_placeholder": "Twoje urodziny", "edit_profile.fields.bot_label": "To jest konto bota", "edit_profile.fields.discoverable_label": "Pozwól na odkrywanie konta", "edit_profile.fields.display_name_label": "Nazwa wyświetlana", @@ -344,16 +373,18 @@ "edit_profile.fields.meta_fields.content_placeholder": "Treść", "edit_profile.fields.meta_fields.label_placeholder": "Podpis", "edit_profile.fields.meta_fields_label": "Metadane profilu", + "edit_profile.fields.show_birthday_label": "Pokazuj moje urodziny", "edit_profile.fields.stranger_notifications_label": "Blokuj powiadomienia od nieznajomych", "edit_profile.fields.verified_display_name": "Zweryfikowani użytkownicy nie mogą zmieniać nazwy wyświetlanej", "edit_profile.hints.accepts_email_list": "Otrzymuj wiadomości i nowości marketingowe.", - "edit_profile.hints.avatar": "PNG, GIF lub JPG. Maksymalnie 2 MB. Zostanie zmniejszony do 400x400px", + "edit_profile.hints.avatar": "PNG, GIF lub JPG. Zostanie zmniejszony do {size}", "edit_profile.hints.bot": "To konto podejmuje głównie zautomatyzowane działania i może nie być nadzorowane", "edit_profile.hints.discoverable": "Wyświetlaj konto w katalogu profilów i pozwalaj na indeksowanie przez zewnętrzne usługi", - "edit_profile.hints.header": "PNG, GIF lub JPG. Maksymalnie 2 MB. Zostanie zmniejszony do 1500x500px", + "edit_profile.hints.header": "PNG, GIF lub JPG. Zostanie zmniejszony do {size}", "edit_profile.hints.hide_network": "To, kogo obserwujesz i kto Cię obserwuje nie będzie wyświetlane na Twoim profilu", "edit_profile.hints.locked": "Wymaga ręcznego zatwierdzania obserwacji", "edit_profile.hints.meta_fields": "Możesz mieć maksymalnie {count, plural, one {# element} few {# elemeny} many {# elementów} other {# elementy}} wyświetlane w formie tabeli na swoim profilu", + "edit_profile.hints.show_birthday": "Twoja data urodzenia będzie widoczna na Twoim profilu.", "edit_profile.hints.stranger_notifications": "Wyświetlaj tylko powiadomienia od osób, które obserwujesz", "edit_profile.meta_fields.add": "Dodaj element", "edit_profile.save": "Zapisz", @@ -390,10 +421,10 @@ "empty_column.filters": "Nie wyciszyłeś(-aś) jeszcze żadnego słowa.", "empty_column.follow_recommendations": "Wygląda na to, że nie można wygenerować dla Ciebie sugestii kont do obserwacji. Możesz spróbować użyć wyszukiwania aby odnaleźć ciekawe profile, lub przejrzeć trendujące hashtagi.", "empty_column.follow_requests": "Nie masz żadnych próśb o możliwość śledzenia. Kiedy ktoś utworzy ją, pojawi się tutaj.", - "empty_column.group": "There is nothing in this group yet. When members of this group make new posts, they will appear here.", + "empty_column.group": "Nie ma żadnych wpisów w tej grupie. Gdy członkowie tej grupy utworzą wpisy, pojawią się one tutaj.", "empty_column.hashtag": "Nie ma wpisów oznaczonych tym hashtagiem. Możesz napisać pierwszy(-a)!", - "empty_column.home": "Nie śledzisz nikogo. Odwiedź globalną oś czasu lub użyj wyszukiwarki, aby znaleźć interesujące Cię profile.", - "empty_column.home.local_tab": "zakładka {site_title}", + "empty_column.home": "Nie śledzisz nikogo. Odwiedź {public}, aby znaleźć innych użytkowników.", + "empty_column.home.local_tab": "zakładkę {site_title}", "empty_column.list": "Nie ma nic na tej liście. Kiedy członkowie listy dodadzą nowe wpisy, pojawia się one tutaj.", "empty_column.lists": "Nie masz żadnych list. Kiedy utworzysz jedną, pojawi się tutaj.", "empty_column.mutes": "Nie wyciszyłeś(-aś) jeszcze żadnego użytkownika.", @@ -449,7 +480,6 @@ "forms.hide_password": "Ukryj hasło", "forms.show_password": "Pokaż hasło", "getting_started.open_source_notice": "{code_name} jest oprogramowaniem o otwartym źródle. Możesz pomóc w rozwoju lub zgłaszać błędy na GitLabie tutaj: {code_link} (v{code_version}).", - "group.detail.archived_group": "Zarchiwizowana grupa", "group.members.empty": "Ta grupa nie ma żadnych członków.", "group.removed_accounts.empty": "Ta grupa nie ma żadnych usuniętych kont.", "groups.card.join": "Dołącz", @@ -458,21 +488,13 @@ "groups.card.roles.member": "Jesteś członkiem", "groups.card.view": "Zobacz", "groups.create": "Utwórz grupę", - "groups.detail.role_admin": "Jesteś administratorem", - "groups.edit": "Edytuj", "groups.form.coverImage": "Wyślij obraz baneru (nieobowiązkowe)", "groups.form.coverImageChange": "Wybrano obraz baneru", "groups.form.create": "Utwórz grupę", "groups.form.description": "Opis", "groups.form.title": "Tytuł", "groups.form.update": "Aktualizuj grupę", - "groups.join": "Dołącz do grupy", - "groups.leave": "Opuść grupę", "groups.removed_accounts": "Usunięte konta", - "groups.sidebar-panel.item.no_recent_activity": "Brak ostatniej aktywności", - "groups.sidebar-panel.item.view": "nowe wpisy", - "groups.sidebar-panel.show_all": "Pokaż wszystkie", - "groups.sidebar-panel.title": "Grupy do których należysz", "groups.tab_admin": "Zarządzaj", "groups.tab_featured": "Wyróżnione", "groups.tab_member": "Członek", @@ -487,14 +509,10 @@ "home.column_settings.show_reblogs": "Pokazuj podbicia", "home.column_settings.show_replies": "Pokazuj odpowiedzi", "home.column_settings.title": "Ustawienia strony głównej", - "home_column.lists": "Listy", - "home_column_header.all": "Wszystkie", - "home_column_header.fediverse": "Fediwersum", - "home_column_header.home": "Strona główna", "icon_button.icons": "Ikony", "icon_button.label": "Wybierz ikonę", "icon_button.not_found": "Brak ikon!! (╯°□°)╯︵ ┻━┻", - "import_data.actions.import": "Import", + "import_data.actions.import": "Importuj", "import_data.actions.import_blocks": "Importuj blokady", "import_data.actions.import_follows": "Importuj obserwacje", "import_data.actions.import_mutes": "Importuj wyciszenia", @@ -510,19 +528,6 @@ "intervals.full.days": "{number, plural, one {# dzień} few {# dni} many {# dni} other {# dni}}", "intervals.full.hours": "{number, plural, one {# godzina} few {# godziny} many {# godzin} other {# godzin}}", "intervals.full.minutes": "{number, plural, one {# minuta} few {# minuty} many {# minut} other {# minut}}", - "introduction.federation.action": "Next", - "introduction.federation.home.headline": "Home", - "introduction.federation.home.text": "Posts from people you follow will appear in your home feed. You can follow anyone on any server!", - "introduction.interactions.action": "Finish tutorial!", - "introduction.interactions.favourite.headline": "Favorite", - "introduction.interactions.favourite.text": "You can save a post for later, and let the author know that you liked it, by favoriting it.", - "introduction.interactions.reblog.headline": "Repost", - "introduction.interactions.reblog.text": "You can share other people's posts with your followers by reposting them.", - "introduction.interactions.reply.headline": "Reply", - "introduction.interactions.reply.text": "You can reply to other people's and your own posts, which will chain them together in a conversation.", - "introduction.welcome.action": "Let's go!", - "introduction.welcome.headline": "First steps", - "introduction.welcome.text": "Welcome to the fediverse! In a few moments, you'll be able to broadcast messages and talk to your friends across a wide variety of servers. But this server, {domain}, is special—it hosts your profile, so remember its name.", "keyboard_shortcuts.back": "aby cofnąć się", "keyboard_shortcuts.blocked": "aby przejść do listy zablokowanych użytkowników", "keyboard_shortcuts.boost": "aby podbić wpis", @@ -556,8 +561,6 @@ "lightbox.previous": "Poprzednie", "lightbox.view_context": "Pokaż kontekst", "list.click_to_add": "Naciśnij tutaj, aby dodać ludzi", - "list.label": "Wybierz listę…", - "list.select": "Wybierz listę", "list_adder.header_title": "Dodaj lub usuń z list", "lists.account.add": "Dodaj do listy", "lists.account.remove": "Usunąć z listy", @@ -583,12 +586,15 @@ "media_gallery.toggle_visible": "Przełącz widoczność", "media_panel.empty_message": "Nie znaleziono mediów.", "media_panel.title": "Media", + "mfa.confirm.success_message": "Potwierdzono MFA", + "mfa.disable.success_message": "Wyłączono MFA", "mfa.mfa_disable_enter_password": "Wprowadź obecne hasło, aby wyłączyć uwierzytelnianie dwuetapowe:", - "mfa.mfa_setup_enter_password": "Wprowadź obecne hasło, aby potwierdzić swoją tożsamość:", + "mfa.mfa_setup.code_hint": "Wprowadź kod z aplikacji do uwierzytelniania dwuskładnikowego.", + "mfa.mfa_setup.code_placeholder": "Kod", + "mfa.mfa_setup.password_hint": "Wprowadź obecne hasło, aby potwierdzić swoją tożsamość.", + "mfa.mfa_setup.password_placeholder": "Hasło", "mfa.mfa_setup_scan_description": "Korzystając z aplikacji do uwierzytelniania dwuetapowego, zeskanuj ten kod QR lub wprowadź klucz tekstowy:", - "mfa.mfa_setup_scan_key": "Klucz:", "mfa.mfa_setup_scan_title": "Skanuj", - "mfa.mfa_setup_verify_description": "Aby aktywować uwierzytelnianie dwuetapowe, wprowadź kod ze swojej aplikacji do uwierzytelniania dwuetapowego:", "mfa.mfa_setup_verify_title": "Weryfikuj", "mfa.otp_enabled_description": "Masz włączone uwierzytelnianie dwuetapowe przez OTP.", "mfa.otp_enabled_title": "Włączono OTP", @@ -615,9 +621,9 @@ "navigation_bar.account_aliases": "Aliasy kont", "navigation_bar.admin_settings": "Ustawienia administracyjne", "navigation_bar.blocks": "Zablokowani użytkownicy", - "navigation_bar.bookmarks": "Zakładki", "navigation_bar.compose": "Utwórz nowy wpis", "navigation_bar.compose_direct": "Wiadomość bezpośrednia", + "navigation_bar.compose_quote": "Cytuj wpis", "navigation_bar.compose_reply": "Odpowiedz na wpis", "navigation_bar.domain_blocks": "Ukryte domeny", "navigation_bar.export_data": "Eksportuj dane", @@ -629,15 +635,16 @@ "navigation_bar.info": "Szczegółowe informacje", "navigation_bar.invites": "Zaproszenia", "navigation_bar.keyboard_shortcuts": "Skróty klawiszowe", - "navigation_bar.lists": "Lists", "navigation_bar.logout": "Wyloguj", - "navigation_bar.messages": "Messages", "navigation_bar.mutes": "Wyciszeni użytkownicy", "navigation_bar.pins": "Przypięte wpisy", "navigation_bar.preferences": "Preferencje", "navigation_bar.profile_directory": "Katalog profilów", "navigation_bar.security": "Bezpieczeństwo", "navigation_bar.soapbox_config": "Konfiguracja Soapbox", + "notification.birthday": "{name} ma dziś urodziny", + "notification.birthday.more": "{count} {count, plural, one {znajomy} other {więcej znajomych}}", + "notification.birthday_plural": "{name} i {more} mają dziś urodziny", "notification.chat_mention": "{name} wysłał(a) Ci wiadomośść", "notification.favourite": "{name} dodał(a) Twój wpis do ulubionych", "notification.follow": "{name} zaczął(-ęła) Cię śledzić", @@ -649,7 +656,10 @@ "notification.reblog": "{name} podbił(a) Twój wpis", "notifications.clear": "Wyczyść powiadomienia", "notifications.clear_confirmation": "Czy na pewno chcesz bezpowrotnie usunąć wszystkie powiadomienia?", + "notifications.clear_heading": "Wyczyść powiadomienia", "notifications.column_settings.alert": "Powiadomienia na pulpicie", + "notifications.column_settings.birthdays.category": "Urodziny", + "notifications.column_settings.birthdays.show": "Pokazuj przypomnienia o urodzinach", "notifications.column_settings.emoji_react": "Reakcje emoji:", "notifications.column_settings.favourite": "Dodanie do ulubionych:", "notifications.column_settings.filter_bar.advanced": "Wyświetl wszystkie kategorie", @@ -697,7 +707,6 @@ "preferences.fields.content_type_label": "Format wpisów", "preferences.fields.delete_modal_label": "Pokazuj prośbę o potwierdzenie przed usunięciem wpisu", "preferences.fields.demetricator_label": "Użyj Demetricatora", - "preferences.fields.developer_label": "Narzędzia dla programistów", "preferences.fields.display_media.default": "Ukrywaj media oznaczone jako wrażliwe", "preferences.fields.display_media.hide_all": "Ukrywaj wszystkie media", "preferences.fields.display_media.show_all": "Pokazuj wszystkie media", @@ -750,7 +759,6 @@ "registration.fields.password_placeholder": "Hasło", "registration.fields.username_hint": "Możesz używać tylko liter, cyfr i podkreślników.", "registration.fields.username_placeholder": "Nazwa użytkownika", - "registration.lead": "Z kontem na {instance}, możesz obserwować ludzi z dowolnego serwera w całym Fediwersum.", "registration.newsletter": "Zasubskrybuj newsletter.", "registration.password_mismatch": "Hasła nie pasują do siebie.", "registration.reason": "Dlaczego chcesz dołączyć?", @@ -764,12 +772,12 @@ "relative_time.minutes": "{number} min.", "relative_time.seconds": "{number} s.", "remote_instance.edit_federation": "Edytuj federację", - "remote_instance.federation_panel.heading": "Federation Restrictions", + "remote_instance.federation_panel.heading": "Ograniczenia federacji", "remote_instance.federation_panel.no_restrictions_message": "{siteTitle} nie nakłada ograniczeń na {host}.", "remote_instance.federation_panel.restricted_message": "{siteTitle} blokuje wszystkie aktywności z {host}.", "remote_instance.federation_panel.some_restrictions_message": "{siteTitle} nakłada pewne ograniczenia na {host}.", - "remote_instance.pin_host": "Przypnij {instance}", - "remote_instance.unpin_host": "Odepnij {instance}", + "remote_instance.pin_host": "Przypnij {host}", + "remote_instance.unpin_host": "Odepnij {host}", "remote_interaction.account_placeholder": "Wprowadź nazwę@domenę użytkownika, z którego chcesz wykonać działanie", "remote_interaction.divider": "lub", "remote_interaction.favourite": "Przejdź do polubienia", @@ -808,7 +816,6 @@ "search_results.accounts": "Ludzie", "search_results.hashtags": "Hashtagi", "search_results.statuses": "Wpisy", - "search_results.top": "Góra", "security.codes.fail": "Nie udało się uzyskać zapasowych kodów", "security.confirm.fail": "Nieprawidłowy kod lub hasło. Spróbuj ponownie.", "security.delete_account.fail": "Nie udało się usunąć konta.", @@ -839,6 +846,7 @@ "security.update_password.success": "Pomyślnie zmieniono hasło.", "signup_panel.subtitle": "Zarejestruj się, aby przyłączyć się do dyskusji.", "signup_panel.title": "Nowi na {site_title}?", + "snackbar.view": "Wyświetl", "soapbox_config.authenticated_profile_hint": "Użytkownicy muszą być zalogowani, aby zobaczyć odpowiedzi i media na profilach użytkowników.", "soapbox_config.authenticated_profile_label": "Profile wymagają uwierzytelniania", "soapbox_config.copyright_footer.meta_fields.label_placeholder": "Stopka praw autorskich", @@ -898,6 +906,7 @@ "status.open": "Rozwiń ten wpis", "status.pin": "Przypnij do profilu", "status.pinned": "Przypięty wpis", + "status.quote": "Cytuj wpis", "status.reactions.cry": "Przykro mi", "status.reactions.empty": "Nikt nie zareagował na ten wpis. Gdy ktoś to zrobi, pojawi się tutaj.", "status.reactions.heart": "Super", @@ -923,7 +932,6 @@ "status.show_less_all": "Zwiń wszystkie", "status.show_more": "Rozwiń", "status.show_more_all": "Rozwiń wszystkie", - "status.show_thread": "Pokaż wątek", "status.title": "Wpis", "status.title_direct": "Wiadomość bezpośrednia", "status.unbookmark": "Usuń z zakładek", @@ -931,6 +939,7 @@ "status.unmute_conversation": "Cofnij wyciszenie konwersacji", "status.unpin": "Odepnij z profilu", "status_list.queue_label": "Naciśnij aby zobaczyć {count} {count, plural, one {nowy wpis} few {nowe wpisy} many {nowych wpisów} other {nowe wpisy}}", + "statuses.quote_tombstone": "Wpis jest niedostępny.", "statuses.tombstone": "Jeden lub więcej z wpisów jest już niedostępny.", "suggestions.dismiss": "Odrzuć sugestię", "tabs_bar.all": "Wszystkie", From c672f7a6ae80f14280ddf47d9cf0b8ba722a08a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Wed, 9 Feb 2022 23:11:45 +0100 Subject: [PATCH 23/30] Don't show 'Bookmark' item menu if not authenticated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/components/status_action_bar.js | 8 ++++---- .../features/status/components/action_bar.js | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/soapbox/components/status_action_bar.js b/app/soapbox/components/status_action_bar.js index 429b092ca..79018e680 100644 --- a/app/soapbox/components/status_action_bar.js +++ b/app/soapbox/components/status_action_bar.js @@ -342,6 +342,10 @@ class StatusActionBar extends ImmutablePureComponent { // }); } + if (!me) { + return menu; + } + if (features.bookmarks) { menu.push({ text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), @@ -350,10 +354,6 @@ class StatusActionBar extends ImmutablePureComponent { }); } - if (!me) { - return menu; - } - menu.push(null); if (ownAccount || withDismiss) { diff --git a/app/soapbox/features/status/components/action_bar.js b/app/soapbox/features/status/components/action_bar.js index b34711632..967702a1a 100644 --- a/app/soapbox/features/status/components/action_bar.js +++ b/app/soapbox/features/status/components/action_bar.js @@ -345,15 +345,15 @@ class ActionBar extends React.PureComponent { // }); } - if (features.bookmarks) { - menu.push({ - text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), - action: this.handleBookmarkClick, - icon: require(status.get('bookmarked') ? '@tabler/icons/icons/bookmark-off.svg' : '@tabler/icons/icons/bookmark.svg'), - }); - } - if (me) { + if (features.bookmarks) { + menu.push({ + text: intl.formatMessage(status.get('bookmarked') ? messages.unbookmark : messages.bookmark), + action: this.handleBookmarkClick, + icon: require(status.get('bookmarked') ? '@tabler/icons/icons/bookmark-off.svg' : '@tabler/icons/icons/bookmark.svg'), + }); + } + menu.push(null); if (ownAccount) { From 012a7f8d89227015c9b3be97510924adca628dc8 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 9 Feb 2022 19:47:13 -0600 Subject: [PATCH 24/30] Mitra: support Ethereum login --- app/soapbox/actions/auth.js | 28 +++++++++++++++ .../auth_login/components/login_form.js | 11 ++---- .../auth_login/components/login_page.js | 35 +++++++++++++++---- app/soapbox/utils/features.js | 2 ++ 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index 5274a98cf..dde684f77 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -213,6 +213,34 @@ export function logIn(intl, username, password) { }; } +export function ethereumLogin() { + return (dispatch, getState) => { + const { ethereum } = window; + const loginMessage = getState().getIn(['instance', 'login_message']); + + return ethereum.request({ method: 'eth_requestAccounts' }).then(walletAddresses => { + const [walletAddress] = walletAddresses; + + return ethereum.request({ method: 'personal_sign', params: [loginMessage, walletAddress] }).then(signature => { + const params = { + grant_type: 'ethereum', + wallet_address: walletAddress.toLowerCase(), + password: signature, + redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', + scope: getScopes(getState()), + }; + + // Note: skips app creation + // TODO: add to quirks.js for Mitra + return dispatch(obtainOAuthToken(params)).then(token => { + dispatch(authLoggedIn(token)); + return dispatch(verifyCredentials(token.access_token)); + }); + }); + }); + }; +} + export function logOut(intl) { return (dispatch, getState) => { const state = getState(); diff --git a/app/soapbox/features/auth_login/components/login_form.js b/app/soapbox/features/auth_login/components/login_form.js index 62b80f0af..549ebb338 100644 --- a/app/soapbox/features/auth_login/components/login_form.js +++ b/app/soapbox/features/auth_login/components/login_form.js @@ -15,11 +15,10 @@ const messages = defineMessages({ const mapStateToProps = state => { const instance = state.get('instance'); - const features = getFeatures(instance); return { baseURL: getBaseURL(state), - hasResetPasswordAPI: features.resetPasswordAPI, + features: getFeatures(instance), }; }; @@ -28,7 +27,7 @@ export default @connect(mapStateToProps) class LoginForm extends ImmutablePureComponent { render() { - const { intl, isLoading, handleSubmit, baseURL, hasResetPasswordAPI } = this.props; + const { intl, isLoading, handleSubmit, baseURL, features } = this.props; return (
@@ -57,12 +56,8 @@ class LoginForm extends ImmutablePureComponent { autoCapitalize='off' required /> - {/*
- -
*/}

- {hasResetPasswordAPI ? ( + {features.resetPasswordAPI ? ( diff --git a/app/soapbox/features/auth_login/components/login_page.js b/app/soapbox/features/auth_login/components/login_page.js index ca16c2a81..d6de2ca3d 100644 --- a/app/soapbox/features/auth_login/components/login_page.js +++ b/app/soapbox/features/auth_login/components/login_page.js @@ -4,18 +4,25 @@ import { injectIntl } from 'react-intl'; import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; +import { ethereumLogin } from 'soapbox/actions/auth'; import { logIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; import { fetchInstance } from 'soapbox/actions/instance'; +import { getFeatures } from 'soapbox/utils/features'; import { isStandalone } from 'soapbox/utils/state'; import LoginForm from './login_form'; import OtpAuthForm from './otp_auth_form'; -const mapStateToProps = state => ({ - me: state.get('me'), - isLoading: false, - standalone: isStandalone(state), -}); +const mapStateToProps = state => { + const instance = state.get('instance'); + + return { + me: state.get('me'), + isLoading: false, + standalone: isStandalone(state), + features: getFeatures(instance), + }; +}; export default @connect(mapStateToProps) @injectIntl @@ -62,8 +69,18 @@ class LoginPage extends ImmutablePureComponent { event.preventDefault(); } + handleEthereumLogin = e => { + const { dispatch } = this.props; + + dispatch(ethereumLogin()) + .then(() => this.setState({ shouldRedirect: true })) + .catch(console.error); + + e.preventDefault(); + }; + render() { - const { standalone } = this.props; + const { standalone, features } = this.props; const { isLoading, mfa_auth_needed, mfa_token, shouldRedirect } = this.state; if (standalone) return ; @@ -72,7 +89,11 @@ class LoginPage extends ImmutablePureComponent { if (mfa_auth_needed) return ; - return ; + if (features.ethereumLogin) { + return ; + } else { + return ; + } } } diff --git a/app/soapbox/utils/features.js b/app/soapbox/utils/features.js index e55ca455c..2df8e1c7a 100644 --- a/app/soapbox/utils/features.js +++ b/app/soapbox/utils/features.js @@ -9,6 +9,7 @@ const any = arr => arr.some(Boolean); // For uglification export const MASTODON = 'Mastodon'; export const PLEROMA = 'Pleroma'; +export const MITRA = 'Mitra'; export const getFeatures = createSelector([ instance => parseVersion(instance.get('version')), @@ -83,6 +84,7 @@ export const getFeatures = createSelector([ accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'), quotePosts: v.software === PLEROMA && gte(v.version, '2.4.50'), birthdays: v.software === PLEROMA && gte(v.version, '2.4.50'), + ethereumLogin: v.software === MITRA, }; }); From f051b70b102cf8d141c7ea3e9dbd056c17a4f073 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 10 Feb 2022 16:33:28 -0600 Subject: [PATCH 25/30] Support Ethereum external login --- app/soapbox/actions/auth.js | 21 +++-- app/soapbox/actions/external_auth.js | 84 +++++++++++++------ .../auth_login/components/login_page.js | 35 ++------ .../components/external_login_form.js | 4 +- app/soapbox/utils/quirks.js | 15 ++-- 5 files changed, 90 insertions(+), 69 deletions(-) diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index dde684f77..65c1dc0f5 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -18,6 +18,7 @@ import KVStore from 'soapbox/storage/kv_store'; import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; +import { getQuirks } from 'soapbox/utils/quirks'; import { isStandalone } from 'soapbox/utils/state'; import api, { baseClient } from '../api'; @@ -62,6 +63,10 @@ function createAppAndToken() { function createAuthApp() { return (dispatch, getState) => { + // Mitra: skip creating the app + const quirks = getQuirks(getState().get('instance')); + if (quirks.skipsAppCreation) return dispatch(noOp()); + const params = { client_name: sourceCode.displayName, redirect_uris: 'urn:ietf:wg:oauth:2.0:oob', @@ -213,10 +218,13 @@ export function logIn(intl, username, password) { }; } -export function ethereumLogin() { +export function ethereumLogin(instance, baseURL) { return (dispatch, getState) => { + instance = (instance || getState().get('instance')); + const { ethereum } = window; - const loginMessage = getState().getIn(['instance', 'login_message']); + const { scopes } = getFeatures(instance); + const loginMessage = instance.get('login_message'); return ethereum.request({ method: 'eth_requestAccounts' }).then(walletAddresses => { const [walletAddress] = walletAddresses; @@ -227,15 +235,14 @@ export function ethereumLogin() { wallet_address: walletAddress.toLowerCase(), password: signature, redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', - scope: getScopes(getState()), + scope: scopes, }; // Note: skips app creation // TODO: add to quirks.js for Mitra - return dispatch(obtainOAuthToken(params)).then(token => { - dispatch(authLoggedIn(token)); - return dispatch(verifyCredentials(token.access_token)); - }); + return dispatch(obtainOAuthToken(params, baseURL)) + .then(token => dispatch(authLoggedIn(token))) + .then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL))); }); }); }; diff --git a/app/soapbox/actions/external_auth.js b/app/soapbox/actions/external_auth.js index b3258ab70..35af6699e 100644 --- a/app/soapbox/actions/external_auth.js +++ b/app/soapbox/actions/external_auth.js @@ -9,11 +9,12 @@ import { Map as ImmutableMap, fromJS } from 'immutable'; import { createApp } from 'soapbox/actions/apps'; -import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; +import { authLoggedIn, verifyCredentials, switchAccount, ethereumLogin } from 'soapbox/actions/auth'; import { obtainOAuthToken } from 'soapbox/actions/oauth'; import { parseBaseURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; +import { getQuirks } from 'soapbox/utils/quirks'; import { baseClient } from '../api'; @@ -32,36 +33,65 @@ const fetchExternalInstance = baseURL => { }); }; -export function createAppAndRedirect(host) { +function createExternalApp(instance, baseURL) { + return (dispatch, getState) => { + const { scopes } = getFeatures(instance); + + const params = { + client_name: sourceCode.displayName, + redirect_uris: `${window.location.origin}/auth/external`, + website: sourceCode.homepage, + scopes, + }; + + return dispatch(createApp(params, baseURL)); + }; +} + +function externalAuthorize(instance, baseURL) { + return (dispatch, getState) => { + const { scopes } = getFeatures(instance); + + return dispatch(createExternalApp(instance, baseURL)).then(app => { + const { client_id, redirect_uri } = app; + + const query = new URLSearchParams({ + client_id, + redirect_uri, + response_type: 'code', + scope: scopes, + }); + + localStorage.setItem('soapbox:external:app', JSON.stringify(app)); + localStorage.setItem('soapbox:external:baseurl', baseURL); + localStorage.setItem('soapbox:external:scopes', scopes); + + window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`; + }); + }; +} + +function externalEthereumLogin(instance, baseURL) { + return (dispatch, getState) => { + return dispatch(ethereumLogin(instance, baseURL)) + .then(account => dispatch(switchAccount(account.id))) + .then(() => window.location.href = '/'); + }; +} + +export function externalLogin(host) { return (dispatch, getState) => { const baseURL = parseBaseURL(host) || parseBaseURL(`https://${host}`); return fetchExternalInstance(baseURL).then(instance => { - const { scopes } = getFeatures(instance); - - const params = { - client_name: sourceCode.displayName, - redirect_uris: `${window.location.origin}/auth/external`, - website: sourceCode.homepage, - scopes, - }; - - return dispatch(createApp(params, baseURL)).then(app => { - const { client_id, redirect_uri } = app; - - const query = new URLSearchParams({ - client_id, - redirect_uri, - response_type: 'code', - scope: scopes, - }); - - localStorage.setItem('soapbox:external:app', JSON.stringify(app)); - localStorage.setItem('soapbox:external:baseurl', baseURL); - localStorage.setItem('soapbox:external:scopes', scopes); - - window.location.href = `${baseURL}/oauth/authorize?${query.toString()}`; - }); + const features = getFeatures(instance); + const quirks = getQuirks(instance); + + if (features.ethereumLogin && quirks.ethereumLoginOnly) { + return dispatch(externalEthereumLogin(instance, baseURL)); + } else { + return dispatch(externalAuthorize(instance, baseURL)); + } }); }; } diff --git a/app/soapbox/features/auth_login/components/login_page.js b/app/soapbox/features/auth_login/components/login_page.js index d6de2ca3d..ca16c2a81 100644 --- a/app/soapbox/features/auth_login/components/login_page.js +++ b/app/soapbox/features/auth_login/components/login_page.js @@ -4,25 +4,18 @@ import { injectIntl } from 'react-intl'; import { connect } from 'react-redux'; import { Redirect } from 'react-router-dom'; -import { ethereumLogin } from 'soapbox/actions/auth'; import { logIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; import { fetchInstance } from 'soapbox/actions/instance'; -import { getFeatures } from 'soapbox/utils/features'; import { isStandalone } from 'soapbox/utils/state'; import LoginForm from './login_form'; import OtpAuthForm from './otp_auth_form'; -const mapStateToProps = state => { - const instance = state.get('instance'); - - return { - me: state.get('me'), - isLoading: false, - standalone: isStandalone(state), - features: getFeatures(instance), - }; -}; +const mapStateToProps = state => ({ + me: state.get('me'), + isLoading: false, + standalone: isStandalone(state), +}); export default @connect(mapStateToProps) @injectIntl @@ -69,18 +62,8 @@ class LoginPage extends ImmutablePureComponent { event.preventDefault(); } - handleEthereumLogin = e => { - const { dispatch } = this.props; - - dispatch(ethereumLogin()) - .then(() => this.setState({ shouldRedirect: true })) - .catch(console.error); - - e.preventDefault(); - }; - render() { - const { standalone, features } = this.props; + const { standalone } = this.props; const { isLoading, mfa_auth_needed, mfa_token, shouldRedirect } = this.state; if (standalone) return ; @@ -89,11 +72,7 @@ class LoginPage extends ImmutablePureComponent { if (mfa_auth_needed) return ; - if (features.ethereumLogin) { - return ; - } else { - return ; - } + return ; } } diff --git a/app/soapbox/features/external_login/components/external_login_form.js b/app/soapbox/features/external_login/components/external_login_form.js index c5da61efb..83a9ccf87 100644 --- a/app/soapbox/features/external_login/components/external_login_form.js +++ b/app/soapbox/features/external_login/components/external_login_form.js @@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; import { connect } from 'react-redux'; -import { createAppAndRedirect, loginWithCode } from 'soapbox/actions/external_auth'; +import { externalLogin, loginWithCode } from 'soapbox/actions/external_auth'; import LoadingIndicator from 'soapbox/components/loading_indicator'; import { SimpleForm, FieldsGroup, TextInput } from 'soapbox/features/forms'; @@ -31,7 +31,7 @@ class ExternalLoginForm extends ImmutablePureComponent { this.setState({ isLoading: true }); - dispatch(createAppAndRedirect(host)) + dispatch(externalLogin(host)) .then(() => this.setState({ isLoading: false })) .catch(() => this.setState({ isLoading: false })); } diff --git a/app/soapbox/utils/quirks.js b/app/soapbox/utils/quirks.js index 764b10e26..e3ec5e651 100644 --- a/app/soapbox/utils/quirks.js +++ b/app/soapbox/utils/quirks.js @@ -1,12 +1,17 @@ -import { parseVersion } from './features'; +import { createSelector } from 'reselect'; + +import { parseVersion, PLEROMA, MITRA } from './features'; // For solving bugs between API implementations -export const getQuirks = instance => { - const v = parseVersion(instance.get('version')); +export const getQuirks = createSelector([ + instance => parseVersion(instance.get('version')), +], (v) => { return { - invertedPagination: v.software === 'Pleroma', + invertedPagination: v.software === PLEROMA, + skipsAppCreation: v.software === MITRA, + ethereumLoginOnly: v.software === MITRA, }; -}; +}); export const getNextLinkName = getState => getQuirks(getState().get('instance')).invertedPagination ? 'prev' : 'next'; From 01dd53328beff3ff44c8c269ab8d8aa41e08acf4 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 10 Feb 2022 16:36:36 -0600 Subject: [PATCH 26/30] Cleanup unused code --- app/soapbox/actions/auth.js | 5 ----- app/soapbox/utils/quirks.js | 1 - 2 files changed, 6 deletions(-) diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index 65c1dc0f5..5da8d579e 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -18,7 +18,6 @@ import KVStore from 'soapbox/storage/kv_store'; import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; -import { getQuirks } from 'soapbox/utils/quirks'; import { isStandalone } from 'soapbox/utils/state'; import api, { baseClient } from '../api'; @@ -63,10 +62,6 @@ function createAppAndToken() { function createAuthApp() { return (dispatch, getState) => { - // Mitra: skip creating the app - const quirks = getQuirks(getState().get('instance')); - if (quirks.skipsAppCreation) return dispatch(noOp()); - const params = { client_name: sourceCode.displayName, redirect_uris: 'urn:ietf:wg:oauth:2.0:oob', diff --git a/app/soapbox/utils/quirks.js b/app/soapbox/utils/quirks.js index e3ec5e651..864f1effd 100644 --- a/app/soapbox/utils/quirks.js +++ b/app/soapbox/utils/quirks.js @@ -8,7 +8,6 @@ export const getQuirks = createSelector([ ], (v) => { return { invertedPagination: v.software === PLEROMA, - skipsAppCreation: v.software === MITRA, ethereumLoginOnly: v.software === MITRA, }; }); From abcd55752da73fe8cd3d3f9d18cad23dee973fb6 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Thu, 10 Feb 2022 19:34:23 -0600 Subject: [PATCH 27/30] Support only external Ethereum auth for now --- app/soapbox/actions/auth.js | 30 ------------------------ app/soapbox/actions/external_auth.js | 34 +++++++++++++++++++++++----- app/soapbox/reducers/instance.js | 4 ++-- app/soapbox/utils/ethereum.js | 26 +++++++++++++++++++++ app/soapbox/utils/quirks.js | 3 ++- 5 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 app/soapbox/utils/ethereum.js diff --git a/app/soapbox/actions/auth.js b/app/soapbox/actions/auth.js index 5da8d579e..5274a98cf 100644 --- a/app/soapbox/actions/auth.js +++ b/app/soapbox/actions/auth.js @@ -213,36 +213,6 @@ export function logIn(intl, username, password) { }; } -export function ethereumLogin(instance, baseURL) { - return (dispatch, getState) => { - instance = (instance || getState().get('instance')); - - const { ethereum } = window; - const { scopes } = getFeatures(instance); - const loginMessage = instance.get('login_message'); - - return ethereum.request({ method: 'eth_requestAccounts' }).then(walletAddresses => { - const [walletAddress] = walletAddresses; - - return ethereum.request({ method: 'personal_sign', params: [loginMessage, walletAddress] }).then(signature => { - const params = { - grant_type: 'ethereum', - wallet_address: walletAddress.toLowerCase(), - password: signature, - redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', - scope: scopes, - }; - - // Note: skips app creation - // TODO: add to quirks.js for Mitra - return dispatch(obtainOAuthToken(params, baseURL)) - .then(token => dispatch(authLoggedIn(token))) - .then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL))); - }); - }); - }; -} - export function logOut(intl) { return (dispatch, getState) => { const state = getState(); diff --git a/app/soapbox/actions/external_auth.js b/app/soapbox/actions/external_auth.js index 35af6699e..c6fc5d340 100644 --- a/app/soapbox/actions/external_auth.js +++ b/app/soapbox/actions/external_auth.js @@ -9,10 +9,11 @@ import { Map as ImmutableMap, fromJS } from 'immutable'; import { createApp } from 'soapbox/actions/apps'; -import { authLoggedIn, verifyCredentials, switchAccount, ethereumLogin } from 'soapbox/actions/auth'; +import { authLoggedIn, verifyCredentials, switchAccount } from 'soapbox/actions/auth'; import { obtainOAuthToken } from 'soapbox/actions/oauth'; import { parseBaseURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; +import { getWalletAndSign } from 'soapbox/utils/ethereum'; import { getFeatures } from 'soapbox/utils/features'; import { getQuirks } from 'soapbox/utils/quirks'; @@ -35,6 +36,9 @@ const fetchExternalInstance = baseURL => { function createExternalApp(instance, baseURL) { return (dispatch, getState) => { + // Mitra: skip creating the auth app + if (getQuirks(instance).noApps) return new Promise(f => f({})); + const { scopes } = getFeatures(instance); const params = { @@ -71,11 +75,29 @@ function externalAuthorize(instance, baseURL) { }; } -function externalEthereumLogin(instance, baseURL) { +export function externalEthereumLogin(instance, baseURL) { return (dispatch, getState) => { - return dispatch(ethereumLogin(instance, baseURL)) - .then(account => dispatch(switchAccount(account.id))) - .then(() => window.location.href = '/'); + const loginMessage = instance.get('login_message'); + + return getWalletAndSign(loginMessage).then(({ wallet, signature }) => { + return dispatch(createExternalApp(instance, baseURL)).then(app => { + const params = { + grant_type: 'ethereum', + wallet_address: wallet.toLowerCase(), + client_id: app.client_id, + client_secret: app.client_secret, + password: signature, + redirect_uri: 'urn:ietf:wg:oauth:2.0:oob', + scope: getFeatures(instance).scopes, + }; + + return dispatch(obtainOAuthToken(params, baseURL)) + .then(token => dispatch(authLoggedIn(token))) + .then(({ access_token }) => dispatch(verifyCredentials(access_token, baseURL))) + .then(account => dispatch(switchAccount(account.id))) + .then(() => window.location.href = '/'); + }); + }); }; } @@ -87,7 +109,7 @@ export function externalLogin(host) { const features = getFeatures(instance); const quirks = getQuirks(instance); - if (features.ethereumLogin && quirks.ethereumLoginOnly) { + if (features.ethereumLogin && quirks.noOAuthForm) { return dispatch(externalEthereumLogin(instance, baseURL)); } else { return dispatch(externalAuthorize(instance, baseURL)); diff --git a/app/soapbox/reducers/instance.js b/app/soapbox/reducers/instance.js index 25a04562e..b0dd8594f 100644 --- a/app/soapbox/reducers/instance.js +++ b/app/soapbox/reducers/instance.js @@ -50,7 +50,7 @@ const initialState = ImmutableMap({ // Build Mastodon configuration from Pleroma instance const pleromaToMastodonConfig = instance => { - return { + return ImmutableMap({ statuses: ImmutableMap({ max_characters: instance.get('max_toot_chars'), }), @@ -60,7 +60,7 @@ const pleromaToMastodonConfig = instance => { min_expiration: instance.getIn(['poll_limits', 'min_expiration']), max_expiration: instance.getIn(['poll_limits', 'max_expiration']), }), - }; + }); }; // Use new value only if old value is undefined diff --git a/app/soapbox/utils/ethereum.js b/app/soapbox/utils/ethereum.js new file mode 100644 index 000000000..3bd8db7b1 --- /dev/null +++ b/app/soapbox/utils/ethereum.js @@ -0,0 +1,26 @@ +export const ethereum = () => window.ethereum; + +export const hasEthereum = () => Boolean(ethereum()); + +// Requests an Ethereum wallet from the browser +// Returns a Promise containing the Ethereum wallet address (string). +export const getWallet = () => { + return ethereum().request({ method: 'eth_requestAccounts' }) + .then(wallets => wallets[0]); +}; + +// Asks the browser to sign a message with Ethereum. +// Returns a Promise containing the signature (string). +export const signMessage = (wallet, message) => { + return ethereum().request({ method: 'personal_sign', params: [message, wallet] }); +}; + +// Combines the above functions. +// Returns an object with the `wallet` and `signature` +export const getWalletAndSign = message => { + return getWallet().then(wallet => { + return signMessage(wallet, message).then(signature => { + return { wallet, signature }; + }); + }); +}; diff --git a/app/soapbox/utils/quirks.js b/app/soapbox/utils/quirks.js index 864f1effd..c64631078 100644 --- a/app/soapbox/utils/quirks.js +++ b/app/soapbox/utils/quirks.js @@ -8,7 +8,8 @@ export const getQuirks = createSelector([ ], (v) => { return { invertedPagination: v.software === PLEROMA, - ethereumLoginOnly: v.software === MITRA, + noApps: v.software === MITRA, + noOAuthForm: v.software === MITRA, }; }); From 66ab33a5504d1185bc49fcb37bc0daaa16e97d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 11 Feb 2022 23:57:49 +0100 Subject: [PATCH 28/30] Fix item deletion on 'Edit profile' and 'Soapbox config' pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- app/soapbox/components/svg_icon.js | 7 +++++-- .../__tests__/__snapshots__/login_form-test.js.snap | 4 ++++ .../__tests__/__snapshots__/login_page-test.js.snap | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/soapbox/components/svg_icon.js b/app/soapbox/components/svg_icon.js index 5e5cd3ce0..ded55c50d 100644 --- a/app/soapbox/components/svg_icon.js +++ b/app/soapbox/components/svg_icon.js @@ -17,10 +17,13 @@ export default class SvgIcon extends React.PureComponent { }; render() { - const { src, className } = this.props; + const { src, className, ...other } = this.props; return ( -

+
); diff --git a/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap b/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap index 67b68261f..ed6a494b2 100644 --- a/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap +++ b/app/soapbox/features/auth_login/components/__tests__/__snapshots__/login_form-test.js.snap @@ -56,7 +56,9 @@ exports[` renders for Mastodon 1`] = ` style={Object {}} >