Page MenuHomePhorge

No OneTemporary

Size
60 KB
Referenced Files
None
Subscribers
None
diff --git a/src/components/user_settings/mfa.js b/src/components/user_settings/mfa.js
index 43c39921d4..4ba9a564c9 100644
--- a/src/components/user_settings/mfa.js
+++ b/src/components/user_settings/mfa.js
@@ -1,131 +1,134 @@
import RecoveryCodes from './mfa_backup_codes.vue'
-
+import TOTP from './mfa_totp.vue'
const Mfa = {
data () {
return {
- settings: {}, // current settings of MFA
+ settings: { // current settings of MFA
+ enabled: false,
+ totp: false
+ },
+ setupState: { // setup mfa
+ state: '', // state of setup. '' -> 'getBackupCodes' -> 'setupOTP' -> 'complete'
+ setupOTPState: '' // state of setup otp. '' -> 'prepare' -> 'confirm' -> 'complete'
+ },
+ backupCodes: {
+ inProgress: false, // progress of fetch codes
+ codes: []
+ },
currentPassword: null,
otpConfirmToken: null,
- backup_codes: [],
otpSettings: {}, // pre-setup setting of OTP. secret key, qrcode url.
- performSetup: null, // step of setup. null -> getBackupCodes -> readyBackupCodes
- performSetupOTP: null, // steps of setup otp. null -> init -> confirm
- disableMethod: null, // disable method MFA
- performGenerateNewCodes: false,
- disableError: null,
- confirmOTPError: null,
+ error: null,
readyInit: false
}
},
- components: {'recovery-codes': RecoveryCodes},
+ components: {'recovery-codes': RecoveryCodes, 'totp-item': TOTP},
computed: {
canEnable () {
- return !this.settings.enabled && this.performSetup === null
- },
- showBackupCodes () {
- return this.waitBackupCodes || this.readyBackupCodes
- },
- waitBackupCodes () {
- return this.performSetup === 'getBackupCodes'
- },
- readyBackupCodes () {
- return this.performSetup === 'readyBackupCodes'
+ return !this.settings.enabled && !this.setupInProgress
},
canSetupOTP () {
return (
- this.readyBackupCodes || this.settings.enabled
+ (this.setupInProgress && this.backupCodesPrepared) ||
+ this.settings.enabled
) && this.settings.totp === false
},
waitPreSetupOTP () {
return this.performSetupOTP === null || this.performSetupOTP === 'init'
+ },
+ disableOTP () {
+ return this.disableMethod === 'otp'
+ },
+ setupInProgress () {
+ return this.setupState.state !== '' && this.setupState.state !== 'complete'
+ },
+ prepareOTP () {
+ return this.setupState.setupOTPState === 'prepare'
+ },
+ confirmOTP () {
+ return this.setupState.setupOTPState === 'confirm'
+ },
+ backupCodesPrepared () {
+ return this.backupCodes.inProgress === false && this.backupCodes.codes.length > 0
}
},
+
methods: {
enableMFA () {
- this.performSetup = 'getBackupCodes'
- this.backupCodes().then((codes) => {
- this.backup_codes = codes
- this.performSetup = 'readyBackupCodes'
+ this.setupState.state = 'getBackupcodes'
+ this.$nextTick(() => {
+ this.startFetchBackupCodes()
+ this.$store.state.api.backendInteractor.generateMfaBackupCodes()
+ .then((res) => this.setBackupCodes(res.codes))
+ .then((res) => { this.setupState.state = 'setupOTP' })
})
},
// gets New Backup codes
- getBackupCodes () {
- this.performGenerateNewCodes = true
- this.backupCodes().then((codes) => {
- this.backup_codes = codes
- this.performGenerateNewCodes = false
+ getNewBackupCodes () {
+ this.$nextTick(() => {
+ this.startFetchBackupCodes()
+ this.$store.state.api.backendInteractor.generateMfaBackupCodes().then(
+ (res) => this.setBackupCodes(res.codes)
+ )
})
},
-
- backupCodes () {
- return new Promise((resolve, reject) => {
- this.$store.state.api.backendInteractor.generateMfaBackupCodes({})
- .then((res) => { resolve(res.codes) })
- })
+ startFetchBackupCodes () {
+ this.backupCodes.inProgress = true
+ this.backupCodes.codes = []
+ },
+ setBackupCodes (codes) {
+ this.backupCodes.codes = codes
+ this.backupCodes.inProgress = false
},
// Setup OTP
- setupOTP () {
- this.performSetupOTP = 'init'
+ setupOTP () { // prepare setup OTP
+ this.setupState.setupOTPState = 'prepare'
this.$store.state.api.backendInteractor.mfaSetupOTP({})
.then((res) => {
this.otpSettings = res
- this.performSetupOTP = 'confirm'
+ this.setupState.setupOTPState = 'confirm'
})
},
- confirmOTP () {
- this.confirmOTPError = null
+ doConfirmOTP () { // handler confirm enable OTP
+ this.error = null
this.$store.state.api.backendInteractor.mfaConfirmOTP({
token: this.otpConfirmToken,
password: this.currentPassword
})
.then((res) => {
if (res.error) {
- this.confirmOTPError = res.error
+ this.error = res.error
return
}
- this.performSetup = null
- this.currentPassword = null
- this.fetchSettings(true)
+ this.completeSetup()
})
},
+
+ completeSetup () {
+ this.setupState.setupOTPState = 'complete'
+ this.setupState.state = 'complete'
+ this.currentPassword = null
+ this.fetchSettings()
+ },
+
// end Setup OTP
- // disable OTP
- handleDisableOTP () {
- this.disableError = null
- this.$store.state.api.backendInteractor.mfaDisableOTP({
- password: this.currentPassword
- })
+ // fetch settings from server
+ fetchSettings () {
+ this.$store.state.api.backendInteractor.fetchSettingsMFA()
.then((res) => {
- if (res.error) {
- this.disableError = res.error
- return
+ this.settings = res.settings
+ if (!this.readyInit) {
+ this.readyInit = true
}
- this.disableMethod = null
- this.currentPassword = null
- this.fetchSettings(true)
})
- },
- // end disable OTP
-
- // fetch settings from server
- fetchSettings (force) {
- if (force || this.settings.enabled === undefined) {
- this.$store.state.api.backendInteractor.fetchSettingsMFA({})
- .then((res) => {
- this.settings = res.settings
- if (!this.readyInit) {
- this.readyInit = true
- }
- })
- }
}
// end fetch settings
},
mounted () {
- this.fetchSettings(true)
+ this.fetchSettings()
}
}
export default Mfa
diff --git a/src/components/user_settings/mfa.vue b/src/components/user_settings/mfa.vue
index 3dd275c1c4..f86d3d868e 100644
--- a/src/components/user_settings/mfa.vue
+++ b/src/components/user_settings/mfa.vue
@@ -1,110 +1,87 @@
<template>
<div class="setting-item mfa-settings" v-if="readyInit">
<div class="mfa-heading">
<h2>{{$t('settings.mfa.title')}}</h2>
<button class="btn btn-default" v-if="canEnable" @click="enableMFA" >
{{$t('general.enable')}}
</button>
</div>
- <div v-if="showBackupCodes" class="setting-item">
- <recovery-codes :codes="backup_codes" :progress="waitBackupCodes" />
+ <div v-if="setupInProgress" class="setting-item">
+ <h4>{{$t('settings.mfa.recovery_codes')}}</h4>
+ <recovery-codes :backupCodes="backupCodes"/>
</div>
<div v-if="canSetupOTP">
- <button class="btn btn-default"
- @click="setupOTP"
- v-if="waitPreSetupOTP"
- :disabled="performSetupOTP === 'init'">
+ <button class="btn btn-default" @click="setupOTP" v-if="!confirmOTP" :disabled="prepareOTP">
{{$t('settings.mfa.setup_otp')}}
</button>
- <i v-if="performSetupOTP === 'init'">
+ <i v-if="prepareOTP">
{{$t('settings.mfa.wait_pre_setup_otp')}}
</i>
- <div v-if="performSetupOTP === 'confirm'">
+ <div v-if="confirmOTP">
<h3>{{$t('settings.mfa.setup_otp')}}</h3>
<h4>{{$t('settings.mfa.scan.title')}}</h4>
<p>{{$t('settings.mfa.scan.desc')}}</p>
<qrcode :value="otpSettings.provisioning_uri" :options="{ width: 200 }"></qrcode>
<p>
{{$t('settings.mfa.scan.secret_code')}}:
{{otpSettings.key}}
</p>
<div>
<h4>{{$t('settings.mfa.verify.title')}}</h4>
<p>{{$t('settings.mfa.verify.desc')}}</p>
<input type="text" v-model="otpConfirmToken">
<p>{{$t('settings.enter_current_password_to_confirm')}}:</p>
<input type="password" v-model="currentPassword">
- <button class="btn btn-default" @click="confirmOTP()">
- {{$t('settings.mfa.confirm_and_enabled')}}
+ <button class="btn btn-default" @click="doConfirmOTP()">
+ {{$t('settings.mfa.confirm_and_enable')}}
</button>
- <div class="alert error" v-if="confirmOTPError">{{confirmOTPError}}</div>
+ <div class="alert error" v-if="error">{{error}}</div>
</div>
</div>
</div>
<div v-if="settings.enabled">
<div class="setting-item">
<!-- Enabled methods -->
<h4>{{$t('settings.mfa.methods')}}</h4>
-
- <div class="method-item" v-if="settings.totp">
- <strong>{{$t('settings.mfa.otp')}}</strong>
- <button class="btn btn-default"
- :disabled="disableMethod === 'totp'"
- @click="disableMethod = 'totp'">
- {{$t('general.disable')}}
- </button>
- </div>
-
- <div v-if="disableMethod === 'totp'">
- {{$t('settings.enter_current_password_to_confirm')}}:
- <input type="password" v-model="currentPassword">
- <button class="btn btn-default" @click="handleDisableOTP">
- {{$t('general.confirm')}}
- </button>
- <button class="btn btn-default" @click="disableMethod = null">
- {{$t('general.cancel')}}
- </button>
- <div class="alert error" v-if="disableError">{{disableError}}</div>
- </div>
-
+ <totp-item v-if="settings.totp" v-on:disable="fetchSettings" />
</div>
<div class="setting-item">
<!-- Generate new recovery codes -->
<button class="btn btn-default"
- :disabled="performGenerateNewCodes"
- @click="getBackupCodes">
+ :disabled="backupCodes.inProgress"
+ @click="getNewBackupCodes">
{{$t('settings.mfa.generate_new_recovery_codes')}}
</button>
+
<p class="alert error">
{{$t('settings.mfa.warning_of_generate_new_codes')}}
</p>
-
- <recovery-codes :codes="backup_codes" :progress="performGenerateNewCodes"/>
-
+ <h4 v-if="backupCodesPrepared">{{$t('settings.mfa.recovery_codes')}}</h4>
+ <recovery-codes :backupCodes="backupCodes"/>
</div>
</div>
</div>
</template>
<script src="./mfa.js"></script>
<style lang="scss">
.mfa-settings {
.mfa-heading, .method-item {
overflow: hidden;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: baseline;
}
}
</style>
diff --git a/src/components/user_settings/mfa_backup_codes.js b/src/components/user_settings/mfa_backup_codes.js
index 3ebd957a91..a0a6b789a3 100644
--- a/src/components/user_settings/mfa_backup_codes.js
+++ b/src/components/user_settings/mfa_backup_codes.js
@@ -1,21 +1,18 @@
export default {
props: {
- progress: {type: Boolean, default: false},
- codes: {
- type: Array,
- default: () => { return [] }
+ backupCodes: {
+ type: Object,
+ default: () => ({
+ inProgress: false,
+ codes: []
+ })
}
},
- data () { return { title: this.progress } },
+ data: () => ({}),
computed: {
- ready () { return this.codes.length > 0 }
- },
- mounted () {
- let unwatch = this.$watch('progress', function (value) {
- if (value) {
- this.title = true
- unwatch()
- }
- })
+ inProgress () {
+ return this.backupCodes.inProgress
+ },
+ ready () { return this.backupCodes.codes.length > 0 }
}
}
diff --git a/src/components/user_settings/mfa_backup_codes.vue b/src/components/user_settings/mfa_backup_codes.vue
index c5de44637c..4174a54924 100644
--- a/src/components/user_settings/mfa_backup_codes.vue
+++ b/src/components/user_settings/mfa_backup_codes.vue
@@ -1,16 +1,18 @@
<template>
-<div class="mfa-recovery-codes">
- <h4 v-if="title">{{$t('settings.mfa.recovery_codes')}}</h4>
- <i v-if="progress">{{$t('settings.mfa.waiting_a_recovery_codes')}}</i>
- <div v-if="ready">
- <p class="warning">{{$t('settings.mfa.recovery_codes_warning')}}</p>
- <ul>
- <li v-for="code in codes">{{code}}</li>
- </ul>
- </div>
+<div>
+ <i v-if="inProgress">{{$t('settings.mfa.waiting_a_recovery_codes')}}</i>
+ <template v-if="ready">
+ <p class="alert warning">{{$t('settings.mfa.recovery_codes_warning')}}</p>
+ <ul><li v-for="code in backupCodes.codes">{{code}}</li></ul>
+ </template>
</div>
</template>
<script src="./mfa_backup_codes.js"></script>
<style lang="scss">
-.warning { color: orange; }
+@import '../../_variables.scss';
+
+.warning {
+ color: $fallback--cOrange;
+ color: var(--cOrange, $fallback--cOrange);
+}
</style>
diff --git a/src/components/user_settings/mfa_totp.js b/src/components/user_settings/mfa_totp.js
new file mode 100644
index 0000000000..59f29c52b8
--- /dev/null
+++ b/src/components/user_settings/mfa_totp.js
@@ -0,0 +1,30 @@
+export default {
+ data: () => ({
+ error: false,
+ currentPassword: '',
+ disable: false,
+ inProgress: false
+ }),
+ methods: {
+ doCancel () { this.disable = false },
+ doDisable () {
+ this.error = null
+ this.disable = true
+ },
+ confirmDisable () {
+ this.error = null
+ this.inProgress = true
+ this.$store.state.api.backendInteractor.mfaDisableOTP({
+ password: this.currentPassword
+ })
+ .then((res) => {
+ this.inProgress = false
+ if (res.error) {
+ this.error = res.error
+ return
+ }
+ this.$emit('disable')
+ })
+ }
+ }
+}
diff --git a/src/components/user_settings/mfa_totp.vue b/src/components/user_settings/mfa_totp.vue
new file mode 100644
index 0000000000..4b74b84f50
--- /dev/null
+++ b/src/components/user_settings/mfa_totp.vue
@@ -0,0 +1,23 @@
+<template>
+<div>
+ <div class="method-item">
+ <strong>{{$t('settings.mfa.otp')}}</strong>
+ <button class="btn btn-default" :disabled="disable" @click="doDisable">
+ {{$t('general.disable')}}
+ </button>
+ </div>
+
+ <div v-if="disable">
+ {{$t('settings.enter_current_password_to_confirm')}}:
+ <input type="password" v-model="currentPassword">
+ <button class="btn btn-default" @click="confirmDisable" :disabled="inProgress">
+ {{$t('general.confirm')}}
+ </button>
+ <button class="btn btn-default" @click="doCancel" :disabled="inProgress">
+ {{$t('general.cancel')}}
+ </button>
+ <div class="alert error" v-if="error">{{error}}</div>
+ </div>
+</div>
+</template>
+<script src="./mfa_totp.js"></script>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 96fb3fa3d9..40f5ebce72 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -1,548 +1,548 @@
{
"chat": {
"title": "Chat"
},
"exporter": {
"export": "Export",
"processing": "Processing, you'll soon be asked to download your file"
},
"features_panel": {
"chat": "Chat",
"gopher": "Gopher",
"media_proxy": "Media proxy",
"scope_options": "Scope options",
"text_limit": "Text limit",
"title": "Features",
"who_to_follow": "Who to follow"
},
"finder": {
"error_fetching_user": "Error fetching user",
"find_user": "Find user"
},
"general": {
"apply": "Apply",
"submit": "Submit",
"more": "More",
"generic_error": "An error occured",
"optional": "optional",
"show_more": "Show more",
"show_less": "Show less",
"cancel": "Cancel",
"disable": "Disable",
"enable": "Enable",
"confirm": "Confirm"
},
"image_cropper": {
"crop_picture": "Crop picture",
"save": "Save",
"save_without_cropping": "Save without cropping",
"cancel": "Cancel"
},
"importer": {
"submit": "Submit",
"success": "Imported successfully.",
"error": "An error occured while importing this file."
},
"login": {
"login": "Log in",
"description": "Log in with OAuth",
"logout": "Log out",
"password": "Password",
"placeholder": "e.g. lain",
"register": "Register",
"username": "Username",
"hint": "Log in to join the discussion",
"verify": "Verify",
"authentication_code": "Authentication code",
"enter_recovery_code": "Enter a recovery code",
"enter_two_factor_code": "Enter a two-factor code",
"recovery_code": "Recovery code",
"heading" : {
"PasswordForm" : "Log in",
"TokenForm" : "Log in",
"TotpForm" : "Two-factor authentication",
"RecoveryForm" : "Two-factor recovery"
}
},
"media_modal": {
"previous": "Previous",
"next": "Next"
},
"nav": {
"about": "About",
"back": "Back",
"chat": "Local Chat",
"friend_requests": "Follow Requests",
"mentions": "Mentions",
"interactions": "Interactions",
"dms": "Direct Messages",
"public_tl": "Public Timeline",
"timeline": "Timeline",
"twkn": "The Whole Known Network",
"user_search": "User Search",
"who_to_follow": "Who to follow",
"preferences": "Preferences"
},
"notifications": {
"broken_favorite": "Unknown status, searching for it...",
"favorited_you": "favorited your status",
"followed_you": "followed you",
"load_older": "Load older notifications",
"notifications": "Notifications",
"read": "Read!",
"repeated_you": "repeated your status",
"no_more_notifications": "No more notifications"
},
"interactions": {
"favs_repeats": "Repeats and Favorites",
"follows": "New follows",
"load_older": "Load older interactions"
},
"post_status": {
"new_status": "Post new status",
"account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.",
"account_not_locked_warning_link": "locked",
"attachments_sensitive": "Mark attachments as sensitive",
"content_type": {
"text/plain": "Plain text",
"text/html": "HTML",
"text/markdown": "Markdown",
"text/bbcode": "BBCode"
},
"content_warning": "Subject (optional)",
"default": "Just landed in L.A.",
"direct_warning_to_all": "This post will be visible to all the mentioned users.",
"direct_warning_to_first_only": "This post will only be visible to the mentioned users at the beginning of the message.",
"posting": "Posting",
"scope_notice": {
"public": "This post will be visible to everyone",
"private": "This post will be visible to your followers only",
"unlisted": "This post will not be visible in Public Timeline and The Whole Known Network"
},
"scope": {
"direct": "Direct - Post to mentioned users only",
"private": "Followers-only - Post to followers only",
"public": "Public - Post to public timelines",
"unlisted": "Unlisted - Do not post to public timelines"
}
},
"registration": {
"bio": "Bio",
"email": "Email",
"fullname": "Display name",
"password_confirm": "Password confirmation",
"registration": "Registration",
"token": "Invite token",
"captcha": "CAPTCHA",
"new_captcha": "Click the image to get a new captcha",
"username_placeholder": "e.g. lain",
"fullname_placeholder": "e.g. Lain Iwakura",
"bio_placeholder": "e.g.\nHi, I'm Lain.\nI’m an anime girl living in suburban Japan. You may know me from the Wired.",
"validations": {
"username_required": "cannot be left blank",
"fullname_required": "cannot be left blank",
"email_required": "cannot be left blank",
"password_required": "cannot be left blank",
"password_confirmation_required": "cannot be left blank",
"password_confirmation_match": "should be the same as password"
}
},
"selectable_list": {
"select_all": "Select all"
},
"settings": {
"app_name": "App name",
"security": "Security",
"require_mfa": "Require two-factor authentication for sign-on",
"get_backup_codes": "Get Backup Codes",
"enter_current_password_to_confirm": "Enter your current password to confirm your identity",
"mfa": {
"otp" : "OTP",
"setup_otp" : "Setup OTP",
"wait_pre_setup_otp" : "waiting pre-setup OTP",
- "confirm_and_enabled" : "Confirm & enable OTP",
+ "confirm_and_enable" : "Confirm & enable OTP",
"title": "Two-factor Authentication",
"generate_new_recovery_codes" : "Generate new recovery codes",
"generate_recovery_codes" : "Generate recovery codes.",
"warning_of_generate_new_codes" : "When you generate new recovery codes, your old codes won’t work anymore.",
"recovery_codes" : "Recovery codes.",
"waiting_a_recovery_codes": "waiting for receiving backup codes",
"recovery_codes_warning" : "Print or copy your recovery codes.",
"methods" : "Enabled methods",
"scan": {
"title": "Scan",
"desc": "Using your two-factor app, scan this QR code or enter text code:",
"secret_code": "Key"
},
"verify": {
"title": "Verify",
"desc": "To enable two-factor authentication, enter the token from your two-factor app:"
}
},
"attachmentRadius": "Attachments",
"attachments": "Attachments",
"autoload": "Enable automatic loading when scrolled to the bottom",
"avatar": "Avatar",
"avatarAltRadius": "Avatars (Notifications)",
"avatarRadius": "Avatars",
"background": "Background",
"bio": "Bio",
"block_export": "Block export",
"block_export_button": "Export your blocks to a csv file",
"block_import": "Block import",
"block_import_error": "Error importing blocks",
"blocks_imported": "Blocks imported! Processing them will take a while.",
"blocks_tab": "Blocks",
"btnRadius": "Buttons",
"cBlue": "Blue (Reply, follow)",
"cGreen": "Green (Retweet)",
"cOrange": "Orange (Favorite)",
"cRed": "Red (Cancel)",
"change_password": "Change Password",
"change_password_error": "There was an issue changing your password.",
"changed_password": "Password changed successfully!",
"collapse_subject": "Collapse posts with subjects",
"composing": "Composing",
"confirm_new_password": "Confirm new password",
"current_avatar": "Your current avatar",
"current_password": "Current password",
"current_profile_banner": "Your current profile banner",
"data_import_export_tab": "Data Import / Export",
"default_vis": "Default visibility scope",
"delete_account": "Delete Account",
"delete_account_description": "Permanently delete your account and all your messages.",
"delete_account_error": "There was an issue deleting your account. If this persists please contact your instance administrator.",
"delete_account_instructions": "Type your password in the input below to confirm account deletion.",
"avatar_size_instruction": "The recommended minimum size for avatar images is 150x150 pixels.",
"export_theme": "Save preset",
"filtering": "Filtering",
"filtering_explanation": "All statuses containing these words will be muted, one per line",
"follow_export": "Follow export",
"follow_export_button": "Export your follows to a csv file",
"follow_import": "Follow import",
"follow_import_error": "Error importing followers",
"follows_imported": "Follows imported! Processing them will take a while.",
"foreground": "Foreground",
"general": "General",
"hide_attachments_in_convo": "Hide attachments in conversations",
"hide_attachments_in_tl": "Hide attachments in timeline",
"hide_muted_posts": "Hide posts of muted users",
"max_thumbnails": "Maximum amount of thumbnails per post",
"hide_isp": "Hide instance-specific panel",
"preload_images": "Preload images",
"use_one_click_nsfw": "Open NSFW attachments with just one click",
"hide_post_stats": "Hide post statistics (e.g. the number of favorites)",
"hide_user_stats": "Hide user statistics (e.g. the number of followers)",
"hide_filtered_statuses": "Hide filtered statuses",
"import_blocks_from_a_csv_file": "Import blocks from a csv file",
"import_followers_from_a_csv_file": "Import follows from a csv file",
"import_theme": "Load preset",
"inputRadius": "Input fields",
"checkboxRadius": "Checkboxes",
"instance_default": "(default: {value})",
"instance_default_simple": "(default)",
"interface": "Interface",
"interfaceLanguage": "Interface language",
"invalid_theme_imported": "The selected file is not a supported Pleroma theme. No changes to your theme were made.",
"limited_availability": "Unavailable in your browser",
"links": "Links",
"lock_account_description": "Restrict your account to approved followers only",
"loop_video": "Loop videos",
"loop_video_silent_only": "Loop only videos without sound (i.e. Mastodon's \"gifs\")",
"mutes_tab": "Mutes",
"play_videos_in_modal": "Play videos directly in the media viewer",
"use_contain_fit": "Don't crop the attachment in thumbnails",
"name": "Name",
"name_bio": "Name & Bio",
"new_password": "New password",
"notification_visibility": "Types of notifications to show",
"notification_visibility_follows": "Follows",
"notification_visibility_likes": "Likes",
"notification_visibility_mentions": "Mentions",
"notification_visibility_repeats": "Repeats",
"no_rich_text_description": "Strip rich text formatting from all posts",
"no_blocks": "No blocks",
"no_mutes": "No mutes",
"hide_follows_description": "Don't show who I'm following",
"hide_followers_description": "Don't show who's following me",
"show_admin_badge": "Show Admin badge in my profile",
"show_moderator_badge": "Show Moderator badge in my profile",
"nsfw_clickthrough": "Enable clickthrough NSFW attachment hiding",
"oauth_tokens": "OAuth tokens",
"token": "Token",
"refresh_token": "Refresh Token",
"valid_until": "Valid Until",
"revoke_token": "Revoke",
"panelRadius": "Panels",
"pause_on_unfocused": "Pause streaming when tab is not focused",
"presets": "Presets",
"profile_background": "Profile Background",
"profile_banner": "Profile Banner",
"profile_tab": "Profile",
"radii_help": "Set up interface edge rounding (in pixels)",
"replies_in_timeline": "Replies in timeline",
"reply_link_preview": "Enable reply-link preview on mouse hover",
"reply_visibility_all": "Show all replies",
"reply_visibility_following": "Only show replies directed at me or users I'm following",
"reply_visibility_self": "Only show replies directed at me",
"autohide_floating_post_button": "Automatically hide New Post button (mobile)",
"saving_err": "Error saving settings",
"saving_ok": "Settings saved",
"search_user_to_block": "Search whom you want to block",
"search_user_to_mute": "Search whom you want to mute",
"security_tab": "Security",
"scope_copy": "Copy scope when replying (DMs are always copied)",
"minimal_scopes_mode": "Minimize post scope selection options",
"set_new_avatar": "Set new avatar",
"set_new_profile_background": "Set new profile background",
"set_new_profile_banner": "Set new profile banner",
"settings": "Settings",
"subject_input_always_show": "Always show subject field",
"subject_line_behavior": "Copy subject when replying",
"subject_line_email": "Like email: \"re: subject\"",
"subject_line_mastodon": "Like mastodon: copy as is",
"subject_line_noop": "Do not copy",
"post_status_content_type": "Post status content type",
"stop_gifs": "Play-on-hover GIFs",
"streaming": "Enable automatic streaming of new posts when scrolled to the top",
"text": "Text",
"theme": "Theme",
"theme_help": "Use hex color codes (#rrggbb) to customize your color theme.",
"theme_help_v2_1": "You can also override certain component's colors and opacity by toggling the checkbox, use \"Clear all\" button to clear all overrides.",
"theme_help_v2_2": "Icons underneath some entries are background/text contrast indicators, hover over for detailed info. Please keep in mind that when using transparency contrast indicators show the worst possible case.",
"tooltipRadius": "Tooltips/alerts",
"upload_a_photo": "Upload a photo",
"user_settings": "User Settings",
"values": {
"false": "no",
"true": "yes"
},
"notifications": "Notifications",
"enable_web_push_notifications": "Enable web push notifications",
"style": {
"switcher": {
"keep_color": "Keep colors",
"keep_shadows": "Keep shadows",
"keep_opacity": "Keep opacity",
"keep_roundness": "Keep roundness",
"keep_fonts": "Keep fonts",
"save_load_hint": "\"Keep\" options preserve currently set options when selecting or loading themes, it also stores said options when exporting a theme. When all checkboxes unset, exporting theme will save everything.",
"reset": "Reset",
"clear_all": "Clear all",
"clear_opacity": "Clear opacity"
},
"common": {
"color": "Color",
"opacity": "Opacity",
"contrast": {
"hint": "Contrast ratio is {ratio}, it {level} {context}",
"level": {
"aa": "meets Level AA guideline (minimal)",
"aaa": "meets Level AAA guideline (recommended)",
"bad": "doesn't meet any accessibility guidelines"
},
"context": {
"18pt": "for large (18pt+) text",
"text": "for text"
}
}
},
"common_colors": {
"_tab_label": "Common",
"main": "Common colors",
"foreground_hint": "See \"Advanced\" tab for more detailed control",
"rgbo": "Icons, accents, badges"
},
"advanced_colors": {
"_tab_label": "Advanced",
"alert": "Alert background",
"alert_error": "Error",
"badge": "Badge background",
"badge_notification": "Notification",
"panel_header": "Panel header",
"top_bar": "Top bar",
"borders": "Borders",
"buttons": "Buttons",
"inputs": "Input fields",
"faint_text": "Faded text"
},
"radii": {
"_tab_label": "Roundness"
},
"shadows": {
"_tab_label": "Shadow and lighting",
"component": "Component",
"override": "Override",
"shadow_id": "Shadow #{value}",
"blur": "Blur",
"spread": "Spread",
"inset": "Inset",
"hint": "For shadows you can also use --variable as a color value to use CSS3 variables. Please note that setting opacity won't work in this case.",
"filter_hint": {
"always_drop_shadow": "Warning, this shadow always uses {0} when browser supports it.",
"drop_shadow_syntax": "{0} does not support {1} parameter and {2} keyword.",
"avatar_inset": "Please note that combining both inset and non-inset shadows on avatars might give unexpected results with transparent avatars.",
"spread_zero": "Shadows with spread > 0 will appear as if it was set to zero",
"inset_classic": "Inset shadows will be using {0}"
},
"components": {
"panel": "Panel",
"panelHeader": "Panel header",
"topBar": "Top bar",
"avatar": "User avatar (in profile view)",
"avatarStatus": "User avatar (in post display)",
"popup": "Popups and tooltips",
"button": "Button",
"buttonHover": "Button (hover)",
"buttonPressed": "Button (pressed)",
"buttonPressedHover": "Button (pressed+hover)",
"input": "Input field"
}
},
"fonts": {
"_tab_label": "Fonts",
"help": "Select font to use for elements of UI. For \"custom\" you have to enter exact font name as it appears in system.",
"components": {
"interface": "Interface",
"input": "Input fields",
"post": "Post text",
"postCode": "Monospaced text in a post (rich text)"
},
"family": "Font name",
"size": "Size (in px)",
"weight": "Weight (boldness)",
"custom": "Custom"
},
"preview": {
"header": "Preview",
"content": "Content",
"error": "Example error",
"button": "Button",
"text": "A bunch of more {0} and {1}",
"mono": "content",
"input": "Just landed in L.A.",
"faint_link": "helpful manual",
"fine_print": "Read our {0} to learn nothing useful!",
"header_faint": "This is fine",
"checkbox": "I have skimmed over terms and conditions",
"link": "a nice lil' link"
}
},
"version": {
"title": "Version",
"backend_version": "Backend Version",
"frontend_version": "Frontend Version"
}
},
"timeline": {
"collapse": "Collapse",
"conversation": "Conversation",
"error_fetching": "Error fetching updates",
"load_older": "Load older statuses",
"no_retweet_hint": "Post is marked as followers-only or direct and cannot be repeated",
"repeated": "repeated",
"show_new": "Show new",
"up_to_date": "Up-to-date",
"no_more_statuses": "No more statuses",
"no_statuses": "No statuses"
},
"status": {
"favorites": "Favorites",
"repeats": "Repeats",
"delete": "Delete status",
"pin": "Pin on profile",
"unpin": "Unpin from profile",
"pinned": "Pinned",
"delete_confirm": "Do you really want to delete this status?",
"reply_to": "Reply to",
"replies_list": "Replies:"
},
"user_card": {
"approve": "Approve",
"block": "Block",
"blocked": "Blocked!",
"deny": "Deny",
"favorites": "Favorites",
"follow": "Follow",
"follow_sent": "Request sent!",
"follow_progress": "Requesting…",
"follow_again": "Send request again?",
"follow_unfollow": "Unfollow",
"followees": "Following",
"followers": "Followers",
"following": "Following!",
"follows_you": "Follows you!",
"its_you": "It's you!",
"media": "Media",
"mute": "Mute",
"muted": "Muted",
"per_day": "per day",
"remote_follow": "Remote follow",
"report": "Report",
"statuses": "Statuses",
"unblock": "Unblock",
"unblock_progress": "Unblocking...",
"block_progress": "Blocking...",
"unmute": "Unmute",
"unmute_progress": "Unmuting...",
"mute_progress": "Muting...",
"admin_menu": {
"moderation": "Moderation",
"grant_admin": "Grant Admin",
"revoke_admin": "Revoke Admin",
"grant_moderator": "Grant Moderator",
"revoke_moderator": "Revoke Moderator",
"activate_account": "Activate account",
"deactivate_account": "Deactivate account",
"delete_account": "Delete account",
"force_nsfw": "Mark all posts as NSFW",
"strip_media": "Remove media from posts",
"force_unlisted": "Force posts to be unlisted",
"sandbox": "Force posts to be followers-only",
"disable_remote_subscription": "Disallow following user from remote instances",
"disable_any_subscription": "Disallow following user at all",
"quarantine": "Disallow user posts from federating",
"delete_user": "Delete user",
"delete_user_confirmation": "Are you absolutely sure? This action cannot be undone."
}
},
"user_profile": {
"timeline_title": "User Timeline",
"profile_does_not_exist": "Sorry, this profile does not exist.",
"profile_loading_error": "Sorry, there was an error loading this profile."
},
"user_reporting": {
"title": "Reporting {0}",
"add_comment_description": "The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:",
"additional_comments": "Additional comments",
"forward_description": "The account is from another server. Send a copy of the report there as well?",
"forward_to": "Forward to {0}",
"submit": "Submit",
"generic_error": "An error occurred while processing your request."
},
"who_to_follow": {
"more": "More",
"who_to_follow": "Who to follow"
},
"tool_tip": {
"media_upload": "Upload Media",
"repeat": "Repeat",
"reply": "Reply",
"favorite": "Favorite",
"user_settings": "User Settings"
},
"upload":{
"error": {
"base": "Upload failed.",
"file_too_big": "File too big [{filesize}{filesizeunit} / {allowedsize}{allowedsizeunit}]",
"default": "Try again later"
},
"file_size_units": {
"B": "B",
"KiB": "KiB",
"MiB": "MiB",
"GiB": "GiB",
"TiB": "TiB"
}
}
}
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index 93412620af..2666689b06 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -1,389 +1,389 @@
{
"chat": {
"title": "Чат"
},
"finder": {
"error_fetching_user": "Пользователь не найден",
"find_user": "Найти пользователя"
},
"general": {
"apply": "Применить",
"submit": "Отправить",
"cancel": "Отмена",
"disable": "Оключить",
"enable": "Включить",
"confirm": "Подтвердить"
},
"login": {
"login": "Войти",
"logout": "Выйти",
"password": "Пароль",
"placeholder": "e.c. lain",
"register": "Зарегистрироваться",
"username": "Имя пользователя",
"verify": "Проверить",
"authentication_code": "Код аутентификации",
"enter_recovery_code": "Ввести код восстановления",
"enter_two_factor_code": "Ввести код аутентификации",
"recovery_code": "Код восстановления",
"heading" : {
"PasswordForm" : "Log in",
"TokenForm" : "Log in",
"TotpForm" : "Двухфакторная аутентификация",
"RecoveryForm" : "Two-factor recovery"
}
},
"nav": {
"back": "Назад",
"chat": "Локальный чат",
"mentions": "Упоминания",
"interactions": "Взаимодействия",
"public_tl": "Публичная лента",
"timeline": "Лента",
"twkn": "Федеративная лента"
},
"notifications": {
"broken_favorite": "Неизвестный статус, ищем...",
"favorited_you": "нравится ваш статус",
"followed_you": "начал(а) читать вас",
"load_older": "Загрузить старые уведомления",
"notifications": "Уведомления",
"read": "Прочесть",
"repeated_you": "повторил(а) ваш статус"
},
"interactions": {
"favs_repeats": "Повторы и фавориты",
"follows": "Новые подписки",
"load_older": "Загрузить старые взаимодействия"
},
"post_status": {
"account_not_locked_warning": "Ваш аккаунт не {0}. Кто угодно может зафоловить вас чтобы прочитать посты только для подписчиков",
"account_not_locked_warning_link": "залочен",
"attachments_sensitive": "Вложения содержат чувствительный контент",
"content_warning": "Тема (не обязательно)",
"default": "Что нового?",
"direct_warning": "Этот пост будет виден только упомянутым пользователям",
"posting": "Отправляется",
"scope_notice": {
"public": "Этот пост будет виден всем",
"private": "Этот пост будет виден только вашим подписчикам",
"unlisted": "Этот пост не будет виден в публичной и федеративной ленте"
},
"scope": {
"direct": "Личное - этот пост видят только те кто в нём упомянут",
"private": "Для подписчиков - этот пост видят только подписчики",
"public": "Публичный - этот пост виден всем",
"unlisted": "Непубличный - этот пост не виден на публичных лентах"
}
},
"registration": {
"bio": "Описание",
"email": "Email",
"fullname": "Отображаемое имя",
"password_confirm": "Подтверждение пароля",
"registration": "Регистрация",
"token": "Код приглашения",
"validations": {
"username_required": "не должно быть пустым",
"fullname_required": "не должно быть пустым",
"email_required": "не должен быть пустым",
"password_required": "не должен быть пустым",
"password_confirmation_required": "не должно быть пустым",
"password_confirmation_match": "должно совпадать с паролем"
}
},
"settings": {
"require_mfa": "Включить двухэтапную аутентификацию для входа в систему",
"get_backup_codes": "Получить резервные коды",
"enter_current_password_to_confirm": "Введите свой текущий пароль",
"mfa": {
"otp" : "OTP",
"setup_otp" : "Настройка OTP",
- "confirm_and_enabled" : "Подтвердить и включить OTP",
+ "confirm_and_enable" : "Подтвердить и включить OTP",
"title": "Двухфакторная аутентификация",
"generate_new_recovery_codes" : "Получить новые коды востановления",
"generate_recovery_codes" : "Коды восстановления",
"recovery_codes" : "Коды восстановления.",
"recovery_codes_warning" : "Распечатайте или скопируйте коды восстановления.",
"methods" : "Методы двухэтапной аутентификации",
"scan": {
"title": "Сканирование",
"desc": "Используйте приложение для двухэтапной аутентификации для сканирования этого QR-код или введите текстовый ключ:",
"secret_code": "Ключ"
},
"verify": {
"title": "Проверить",
"desc": "Чтобы включить двухэтапную аутентификации, введите токен из вашего приложение для двухэтапной аутентификации:"
}
},
"attachmentRadius": "Прикреплённые файлы",
"attachments": "Вложения",
"autoload": "Включить автоматическую загрузку при прокрутке вниз",
"avatar": "Аватар",
"avatarAltRadius": "Аватары в уведомлениях",
"avatarRadius": "Аватары",
"background": "Фон",
"bio": "Описание",
"btnRadius": "Кнопки",
"cBlue": "Ответить, читать",
"cGreen": "Повторить",
"cOrange": "Нравится",
"cRed": "Отменить",
"change_password": "Сменить пароль",
"change_password_error": "Произошла ошибка при попытке изменить пароль.",
"changed_password": "Пароль изменён успешно.",
"collapse_subject": "Сворачивать посты с темой",
"confirm_new_password": "Подтверждение нового пароля",
"current_avatar": "Текущий аватар",
"current_password": "Текущий пароль",
"current_profile_banner": "Текущий баннер профиля",
"data_import_export_tab": "Импорт / Экспорт данных",
"delete_account": "Удалить аккаунт",
"delete_account_description": "Удалить ваш аккаунт и все ваши сообщения.",
"delete_account_error": "Возникла ошибка в процессе удаления вашего аккаунта. Если это повторяется, свяжитесь с администратором вашего сервера.",
"delete_account_instructions": "Введите ваш пароль в поле ниже для подтверждения удаления.",
"export_theme": "Сохранить Тему",
"filtering": "Фильтрация",
"filtering_explanation": "Все статусы, содержащие данные слова, будут игнорироваться, по одному в строке",
"follow_export": "Экспортировать читаемых",
"follow_export_button": "Экспортировать читаемых в файл .csv",
"follow_export_processing": "Ведётся обработка, скоро вам будет предложено загрузить файл",
"follow_import": "Импортировать читаемых",
"follow_import_error": "Ошибка при импортировании читаемых.",
"follows_imported": "Список читаемых импортирован. Обработка займёт некоторое время..",
"foreground": "Передний план",
"general": "Общие",
"hide_attachments_in_convo": "Прятать вложения в разговорах",
"hide_attachments_in_tl": "Прятать вложения в ленте",
"hide_isp": "Скрыть серверную панель",
"import_followers_from_a_csv_file": "Импортировать читаемых из файла .csv",
"import_theme": "Загрузить Тему",
"inputRadius": "Поля ввода",
"checkboxRadius": "Чекбоксы",
"instance_default": "(по умолчанию: {value})",
"instance_default_simple": "(по умолчанию)",
"interface": "Интерфейс",
"interfaceLanguage": "Язык интерфейса",
"limited_availability": "Не доступно в вашем браузере",
"links": "Ссылки",
"lock_account_description": "Аккаунт доступен только подтверждённым подписчикам",
"loop_video": "Зациливать видео",
"loop_video_silent_only": "Зацикливать только беззвучные видео (т.е. \"гифки\" с Mastodon)",
"name": "Имя",
"name_bio": "Имя и описание",
"new_password": "Новый пароль",
"notification_visibility": "Показывать уведомления",
"notification_visibility_follows": "Подписки",
"notification_visibility_likes": "Лайки",
"notification_visibility_mentions": "Упоминания",
"notification_visibility_repeats": "Повторы",
"no_rich_text_description": "Убрать форматирование из всех постов",
"hide_follows_description": "Не показывать кого я читаю",
"hide_followers_description": "Не показывать кто читает меня",
"show_admin_badge": "Показывать значок администратора в моем профиле",
"show_moderator_badge": "Показывать значок модератора в моем профиле",
"nsfw_clickthrough": "Включить скрытие NSFW вложений",
"oauth_tokens": "OAuth токены",
"token": "Токен",
"refresh_token": "Рефреш токен",
"valid_until": "Годен до",
"revoke_token": "Удалить",
"panelRadius": "Панели",
"pause_on_unfocused": "Приостановить загрузку когда вкладка не в фокусе",
"presets": "Пресеты",
"profile_background": "Фон профиля",
"profile_banner": "Баннер профиля",
"profile_tab": "Профиль",
"radii_help": "Скругление углов элементов интерфейса (в пикселях)",
"replies_in_timeline": "Ответы в ленте",
"reply_link_preview": "Включить предварительный просмотр ответа при наведении мыши",
"reply_visibility_all": "Показывать все ответы",
"reply_visibility_following": "Показывать только ответы мне и тех на кого я подписан",
"reply_visibility_self": "Показывать только ответы мне",
"autohide_floating_post_button": "Автоматически скрывать кнопку постинга (в мобильной версии)",
"saving_err": "Не удалось сохранить настройки",
"saving_ok": "Сохранено",
"security_tab": "Безопасность",
"scope_copy": "Копировать видимость поста при ответе (всегда включено для Личных Сообщений)",
"minimal_scopes_mode": "Минимизировать набор опций видимости поста",
"set_new_avatar": "Загрузить новый аватар",
"set_new_profile_background": "Загрузить новый фон профиля",
"set_new_profile_banner": "Загрузить новый баннер профиля",
"settings": "Настройки",
"subject_input_always_show": "Всегда показывать поле ввода темы",
"stop_gifs": "Проигрывать GIF анимации только при наведении",
"streaming": "Включить автоматическую загрузку новых сообщений при прокрутке вверх",
"text": "Текст",
"theme": "Тема",
"theme_help": "Используйте шестнадцатеричные коды цветов (#rrggbb) для настройки темы.",
"theme_help_v2_1": "Вы так же можете перепоределить цвета определенных компонентов нажав соотв. галочку. Используйте кнопку \"Очистить всё\" чтобы снять все переопределения",
"theme_help_v2_2": "Под некоторыми полями ввода это идикаторы контрастности, наведите на них мышью чтобы узнать больше. Приспользовании прозрачности контраст расчитывается для наихудшего варианта.",
"tooltipRadius": "Всплывающие подсказки/уведомления",
"user_settings": "Настройки пользователя",
"values": {
"false": "нет",
"true": "да"
},
"style": {
"switcher": {
"keep_color": "Оставить цвета",
"keep_shadows": "Оставить тени",
"keep_opacity": "Оставить прозрачность",
"keep_roundness": "Оставить скругление",
"keep_fonts": "Оставить шрифты",
"save_load_hint": "Опции \"оставить...\" позволяют сохранить текущие настройки при выборе другой темы или импорта её из файла. Так же они влияют на то какие компоненты будут сохранены при экспорте темы. Когда все галочки сняты все компоненты будут экспортированы.",
"reset": "Сбросить",
"clear_all": "Очистить всё",
"clear_opacity": "Очистить прозрачность"
},
"common": {
"color": "Цвет",
"opacity": "Прозрачность",
"contrast": {
"hint": "Уровень контраста: {ratio}, что {level} {context}",
"level": {
"aa": "соответствует гайдлайну Level AA (минимальный)",
"aaa": "соответствует гайдлайну Level AAA (рекомендуемый)",
"bad": "не соответствует каким либо гайдлайнам"
},
"context": {
"18pt": "для крупного (18pt+) текста",
"text": "для текста"
}
}
},
"common_colors": {
"_tab_label": "Общие",
"main": "Общие цвета",
"foreground_hint": "См. вкладку \"Дополнительно\" для более детального контроля",
"rgbo": "Иконки, акценты, ярылки"
},
"advanced_colors": {
"_tab_label": "Дополнительно",
"alert": "Фон уведомлений",
"alert_error": "Ошибки",
"badge": "Фон значков",
"badge_notification": "Уведомления",
"panel_header": "Заголовок панели",
"top_bar": "Верняя полоска",
"borders": "Границы",
"buttons": "Кнопки",
"inputs": "Поля ввода",
"faint_text": "Маловажный текст"
},
"radii": {
"_tab_label": "Скругление"
},
"shadows": {
"_tab_label": "Светотень",
"component": "Компонент",
"override": "Переопределить",
"shadow_id": "Тень №{value}",
"blur": "Размытие",
"spread": "Разброс",
"inset": "Внутренняя",
"hint": "Для теней вы так же можете использовать --variable в качестве цвета чтобы использовать CSS3-переменные. В таком случае прозрачность работать не будет.",
"filter_hint": {
"always_drop_shadow": "Внимание, эта тень всегда использует {0} когда браузер поддерживает это",
"drop_shadow_syntax": "{0} не поддерживает параметр {1} и ключевое слово {2}",
"avatar_inset": "Одновременное использование внутренних и внешних теней на (прозрачных) аватарках может дать не те результаты что вы ожидаете",
"spread_zero": "Тени с разбросом > 0 будут выглядеть как если бы разброс установлен в 0",
"inset_classic": "Внутренние тени будут использовать {0}"
},
"components": {
"panel": "Панель",
"panelHeader": "Заголовок панели",
"topBar": "Верхняя полоска",
"avatar": "Аватарка (профиль)",
"avatarStatus": "Аватарка (в ленте)",
"popup": "Всплывающие подсказки",
"button": "Кнопки",
"buttonHover": "Кнопки (наведен курсор)",
"buttonPressed": "Кнопки (нажата)",
"buttonPressedHover": "Кнопки (нажата+наведен курсор)",
"input": "Поля ввода"
}
},
"fonts": {
"_tab_label": "Шрифты",
"help": "Выберите тип шрифта для использования в интерфейсе. При выборе варианта \"другой\" надо ввести название шрифта в точности как он называется в системе.",
"components": {
"interface": "Интерфейс",
"input": "Поля ввода",
"post": "Текст постов",
"postCode": "Моноширинный текст в посте (форматирование)"
},
"family": "Шрифт",
"size": "Размер (в пикселях)",
"weight": "Ширина",
"custom": "Другой"
},
"preview": {
"header": "Пример",
"content": "Контент",
"error": "Ошибка стоп 000",
"button": "Кнопка",
"text": "Еще немного {0} и масенькая {1}",
"mono": "контента",
"input": "Что нового?",
"faint_link": "Его придется убрать",
"fine_print": "Если проблемы остались — ваш гуртовщик мыши плохо стоит. {0}.",
"header_faint": "Все идет по плану",
"checkbox": "Я подтверждаю что не было ни единого разрыва",
"link": "ссылка"
}
}
},
"timeline": {
"collapse": "Свернуть",
"conversation": "Разговор",
"error_fetching": "Ошибка при обновлении",
"load_older": "Загрузить старые статусы",
"no_retweet_hint": "Пост помечен как \"только для подписчиков\" или \"личное\" и поэтому не может быть повторён",
"repeated": "повторил(а)",
"show_new": "Показать новые",
"up_to_date": "Обновлено"
},
"user_card": {
"block": "Заблокировать",
"blocked": "Заблокирован",
"favorites": "Понравившиеся",
"follow": "Читать",
"follow_sent": "Запрос отправлен!",
"follow_progress": "Запрашиваем…",
"follow_again": "Запросить еще заново?",
"follow_unfollow": "Перестать читать",
"followees": "Читаемые",
"followers": "Читатели",
"following": "Читаю",
"follows_you": "Читает вас",
"mute": "Игнорировать",
"muted": "Игнорирую",
"per_day": "в день",
"remote_follow": "Читать удалённо",
"statuses": "Статусы",
"admin_menu": {
"moderation": "Опции модератора",
"grant_admin": "Сделать администратором",
"revoke_admin": "Забрать права администратора",
"grant_moderator": "Сделать модератором",
"revoke_moderator": "Забрать права модератора",
"activate_account": "Активировать аккаунт",
"deactivate_account": "Деактивировать аккаунт",
"delete_account": "Удалить аккаунт",
"force_nsfw": "Отмечать посты пользователя как NSFW",
"strip_media": "Убирать вложения из постов пользователя",
"force_unlisted": "Не добавлять посты в публичные ленты",
"sandbox": "Посты доступны только для подписчиков",
"disable_remote_subscription": "Запретить подписываться с удаленных серверов",
"disable_any_subscription": "Запретить подписываться на пользователя",
"quarantine": "Не федерировать посты пользователя",
"delete_user": "Удалить пользователя",
"delete_user_confirmation": "Вы уверены? Это действие нельзя отменить."
}
},
"user_profile": {
"timeline_title": "Лента пользователя"
}
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Oct 9, 4:25 AM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1784440
Default Alt Text
(60 KB)

Event Timeline