Merge branch 'master' of https://github.com/openvk/openvk into ton-integration

This commit is contained in:
veselcraft 2022-05-07 02:27:05 +03:00
commit 13bc1b877d
No known key found for this signature in database
GPG key ID: AED66BC1AC628A4E
12 changed files with 498 additions and 20 deletions

View file

@ -0,0 +1,204 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Подтверждение изменения Email</title>
<link rel="stylesheet" href="foundation.css" />
<style>
.container {
border-top: 5px solid pink;
}
</style>
</head>
<body>
<table class="body" data-made-with-foundation="">
<tr>
<td class="float-center" align="center" valign="top">
<center>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<table class="container">
<tr>
<td>
<table class="row header">
<tr>
<th class="small-12 large-12 columns first last">
<table>
<tr>
<th>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<h4 class="text-center">Подтверждение изменения Email</h4>
</th>
</tr>
</table>
</th>
</tr>
</table>
<table class="row">
<tr>
<th class="small-12 large-12 columns first last">
<table class="row">
<tr>
<td>
<center>
<img src="pictures/lock.jpeg" align="center" class="float-center" width=128 height=128 />
</center>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<hr/>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<p class="text-left">
Здравствуйте, {$name}! Вы вероятно изменили свой адрес электронной почты в OpenVK. Чтобы изменение вступило в силу, необходимо подтвердить ваш новый Email.
</p>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<table class="button large expand success">
<tr>
<td>
<table>
<tr>
<td>
<center>
<a href="http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={rawurlencode($key)}" align="center" class="float-center">Подтвердить Email!</a>
</center>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<p class="text-left">
Если кнопка не работает, вы можете попробовать скопировать и вставить эту ссылку в адресную строку вашего веб-обозревателя:
</p>
<table class="callout">
<tr>
<th class="callout-inner primary">
<a href="http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key}" style="color: #000; text-decoration: none;">
http://{$_SERVER['HTTP_HOST']}/settings/change_email?key={$key}
</a>
</th>
</tr>
</table>
<p class="text-left">
Обратите внимание на то, что эту ссылку нельзя:
</p>
<ul>
<li>Передавать другим людям (даже друзьям, питомцам, соседам, любимым девушкам)</li>
<li>Использовать, если прошло более двух дней с её генерации</li>
</ul>
<table class="callout">
<tr>
<th class="callout-inner alert">
<p>
Ещё раз <b>обратите внимание</b> на то, что данную ссылку или письмо <b>ни в коем случае нельзя</b> передавать другим людям! Даже если они представляются службой поддержки.<br/>
Это письмо предназначено исключительно для одноразового, <b>непосредственного</b> использования владельцем аккаунта.
</p>
</th>
</tr>
</table>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<p class="text-right">
С уважением, овк-тян.
</p>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<hr/>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
<p class="text-left">
<small>
Вы получили это письмо так как кто-то или вы изменили адрес электронной почты. Это не рассылка и от неё нельзя отписаться. Если вы всё равно хотите перестать получать подобные письма, деактивируйте ваш аккаунт.
</small>
</p>
</td>
</tr>
</table>
</th>
</tr>
</table>
</td>
</tr>
</table>
<table class="spacer">
<tr>
<td>
&nbsp;
</td>
</tr>
</table>
</center>
</td>
</tr>
</table>
</body>
</html>

View file

@ -23,11 +23,12 @@ final class Wall extends VKAPIRequestHandler
foreach ($posts->getPostsFromUsersWall((int)$owner_id, 1, $count, $offset) as $post) {
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
$attachments;
foreach($post->getChildren() as $attachment)
{
if($attachment instanceof \openvk\Web\Models\Entities\Photo)
{
$attachments = [];
foreach($post->getChildren() as $attachment) {
if($attachment instanceof \openvk\Web\Models\Entities\Photo) {
if($attachment->isDeleted())
continue;
$attachments[] = [
"type" => "photo",
"photo" => [

View file

@ -0,0 +1,15 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
use openvk\Web\Util\DateTime;
class EmailChangeVerification extends PasswordReset
{
protected $tableName = "email_change_verifications";
function getNewEmail(): string
{
return $this->getRecord()->new_email;
}
}

View file

@ -877,6 +877,17 @@ class User extends RowModel
return true;
}
function setEmail(string $email): void
{
DatabaseConnection::i()->getContext()->table("ChandlerUsers")
->where("id", $this->getChandlerUser()->getId())->update([
"login" => $email
]);
$this->stateChanges("email", $email);
$this->save();
}
function adminNotify(string $message): bool
{
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];

View file

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use openvk\Web\Models\Entities\EmailChangeVerification;
use openvk\Web\Models\Entities\User;
use Nette\Database\Table\ActiveRow;
class EmailChangeVerifications
{
private $context;
private $verifications;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->verifications = $this->context->table("email_change_verifications");
}
function toEmailChangeVerification(?ActiveRow $ar): ?EmailChangeVerification
{
return is_null($ar) ? NULL : new EmailChangeVerification($ar);
}
function getByToken(string $token): ?EmailChangeVerification
{
return $this->toEmailChangeVerification($this->verifications->where("key", $token)->fetch());
}
function getLatestByUser(User $user): ?EmailChangeVerification
{
return $this->toEmailChangeVerification($this->verifications->where("profile", $user->getId())->order("timestamp DESC")->fetch());
}
}

View file

@ -9,12 +9,15 @@ use openvk\Web\Models\Repositories\Albums;
use openvk\Web\Models\Repositories\Videos;
use openvk\Web\Models\Repositories\Notes;
use openvk\Web\Models\Repositories\Vouchers;
use openvk\Web\Models\Repositories\EmailChangeVerifications;
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use openvk\Web\Util\Validator;
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
use openvk\Web\Models\Entities\EmailChangeVerification;
use Chandler\Security\Authenticator;
use lfkeitel\phptotp\{Base32, Totp};
use chillerlan\QRCode\{QRCode, QROptions};
use Nette\Database\UniqueConstraintViolationException;
final class UserPresenter extends OpenVKPresenter
{
@ -132,7 +135,7 @@ final class UserPresenter extends OpenVKPresenter
if(!$id)
$this->notFound();
$user = $this->users->get($id);
if($_SERVER["REQUEST_METHOD"] === "POST") {
$this->willExecuteWriteAction($_GET['act'] === "status");
@ -300,7 +303,7 @@ final class UserPresenter extends OpenVKPresenter
if(!$id)
$this->notFound();
if(in_array($this->queryParam("act"), ["finance", "finance.top-up"]) && !OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
$this->flashFail("err", tr("error"), tr("feature_disabled"));
@ -312,7 +315,7 @@ final class UserPresenter extends OpenVKPresenter
if($this->postParam("old_pass") && $this->postParam("new_pass") && $this->postParam("repeat_pass")) {
if($this->postParam("new_pass") === $this->postParam("repeat_pass")) {
if($this->user->identity->is2faEnabled()) {
$code = $this->postParam("code");
$code = $this->postParam("password_change_code");
if(!($code === (new Totp)->GenerateToken(Base32::decode($this->user->identity->get2faSecret())) || $this->user->identity->use2faBackupCode((int) $code)))
$this->flashFail("err", tr("error"), tr("incorrect_2fa_code"));
}
@ -323,6 +326,46 @@ final class UserPresenter extends OpenVKPresenter
$this->flashFail("err", tr("error"), tr("error_new_password"));
}
}
if($this->postParam("new_email")) {
if(!Validator::i()->emailValid($this->postParam("new_email")))
$this->flashFail("err", tr("invalid_email_address"), tr("invalid_email_address_comment"));
if(!Authenticator::verifyHash($this->postParam("email_change_pass"), $user->getChandlerUser()->getRaw()->passwordHash))
$this->flashFail("err", tr("error"), tr("incorrect_password"));
if($user->is2faEnabled()) {
$code = $this->postParam("email_change_code");
if(!($code === (new Totp)->GenerateToken(Base32::decode($user->get2faSecret())) || $user->use2faBackupCode((int) $code)))
$this->flashFail("err", tr("error"), tr("incorrect_2fa_code"));
}
if($this->postParam("new_email") !== $user->getEmail()) {
if (OPENVK_ROOT_CONF['openvk']['preferences']['security']['requireEmail']) {
$request = (new EmailChangeVerifications)->getLatestByUser($user);
if(!is_null($request) && $request->isNew())
$this->flashFail("err", tr("forbidden"), tr("email_rate_limit_error"));
$verification = new EmailChangeVerification;
$verification->setProfile($user->getId());
$verification->setNew_Email($this->postParam("new_email"));
$verification->save();
$params = [
"key" => $verification->getKey(),
"name" => $user->getCanonicalName(),
];
$this->sendmail($this->postParam("new_email"), "change-email", $params); #Vulnerability possible
$this->flashFail("succ", tr("information_-1"), tr("email_change_confirm_message"));
}
try {
$user->setEmail($this->postParam("new_email"));
} catch(UniqueConstraintViolationException $ex) {
$this->flashFail("err", tr("error"), tr("user_already_exists"));
}
}
}
if(!$user->setShortCode(empty($this->postParam("sc")) ? NULL : $this->postParam("sc")))
$this->flashFail("err", tr("error"), tr("error_shorturl_incorrect"));
@ -400,11 +443,7 @@ final class UserPresenter extends OpenVKPresenter
throw $ex;
}
$this->flash(
"succ",
"Изменения сохранены",
"Новые данные появятся на вашей странице."
);
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
}
$this->template->mode = in_array($this->queryParam("act"), [
"main", "privacy", "finance", "finance.top-up", "interface"
@ -502,6 +541,9 @@ final class UserPresenter extends OpenVKPresenter
$this->assertUserLoggedIn();
$this->willExecuteWriteAction();
if(!OPENVK_ROOT_CONF["openvk"]["preferences"]["commerce"])
$this->flashFail("err", tr("error"), tr("feature_disabled"));
$receiverAddress = $this->postParam("receiver");
$value = (int) $this->postParam("value");
$message = $this->postParam("message");
@ -517,7 +559,7 @@ final class UserPresenter extends OpenVKPresenter
$receiver = $this->users->getByAddress($receiverAddress);
if(!$receiver)
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("receiver_not_found"));
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("receiver_not_found"));
if($this->user->identity->getCoins() < $value)
$this->flashFail("err", tr("failed_to_tranfer_points"), tr("you_dont_have_enough_points"));
@ -574,4 +616,24 @@ final class UserPresenter extends OpenVKPresenter
$this->flashFail("succ", tr("information_-1"), tr("rating_increase_successful", $receiver->getURL(), htmlentities($receiver->getCanonicalName()), $value));
}
function renderEmailChangeFinish(): void
{
$request = (new EmailChangeVerifications)->getByToken(str_replace(" ", "+", $this->queryParam("key")));
if(!$request || !$request->isStillValid()) {
$this->flash("err", tr("token_manipulation_error"), tr("token_manipulation_error_comment"));
$this->redirect("/settings");
} else {
$request->delete(false);
try {
$request->getUser()->setEmail($request->getNewEmail());
} catch(UniqueConstraintViolationException $ex) {
$this->flashFail("err", tr("error"), tr("user_already_exists"));
}
$this->flash("succ", tr("changes_saved"), tr("changes_saved_comment"));
$this->redirect("/settings");
}
}
}

View file

@ -64,7 +64,7 @@
<span class="nobold">{_"2fa_code"}</span>
</td>
<td>
<input type="text" name="code" style="width: 100%;" />
<input type="text" name="password_change_code" style="width: 100%;" />
</td>
</tr>
<tr>
@ -154,6 +154,38 @@
{$user->getEmail()}
</td>
</tr>
<tr>
<td width="120" valign="top">
<span class="nobold">{_new_email_address}</span>
</td>
<td>
<input type="email" name="new_email" style="width: 100%;" />
</td>
</tr>
<tr>
<td width="120" valign="top">
<span class="nobold">{_password}</span>
</td>
<td>
<input type="password" name="email_change_pass" style="width: 100%;" />
</td>
</tr>
<tr n:if="$user->is2faEnabled()">
<td width="120" valign="top">
<span class="nobold">{_"2fa_code"}</span>
</td>
<td>
<input type="text" name="email_change_code" style="width: 100%;" />
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="submit" value="{_save_email_address}" class="button" />
</td>
</tr>
</tbody>
</table>
<br/>

View file

@ -73,6 +73,8 @@ routes:
handler: "User->disableTwoFactorAuth"
- url: "/settings/reset_theme"
handler: "User->resetThemepack"
- url: "/settings/change_email"
handler: "User->emailChangeFinish"
- url: "/coins_transfer"
handler: "User->coinsTransfer"
- url: "/increase_social_credits"

View file

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS `email_change_verifications` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`profile` bigint(20) unsigned NOT NULL,
`key` char(64) COLLATE utf8mb4_unicode_520_ci NOT NULL,
`new_email` varchar(90) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL,
`timestamp` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

View file

@ -9,6 +9,7 @@
"home" = "Գլխավոր";
"welcome" = "Բարի գալուստ";
"to_top" = "Վերև";
/* Login */
@ -381,7 +382,6 @@
"left_menu_donate" = "Աջակցել";
"footer_about_instance" = "հոսքի մասին";
"footer_blog" = "բլոգ";
"footer_help" = "օգնություն";
@ -410,6 +410,8 @@
"style" = "Ոճ";
"default" = "Սովորական";
"arbitrary_avatars" = "Կամայական";
"cut" = "Կտրվածք";
"round_avatars" = "Կլոր ավատար";
@ -519,6 +521,8 @@
"videos_many" = "$1 տեսանյութ";
"videos_other" = "$1 տեսանյութ";
"view_video" = "Դիտում";
/* Notifications */
"feedback" = "Հետադարձ կապ";
@ -624,6 +628,21 @@
"receiver_not_found" = "Ստացողը չի գտնվել։";
"you_dont_have_enough_points" = "Դուք չունե՛ք բավական ձայն։";
"increase_rating" = "Բարձրացնել վարկանիշը";
"increase_rating_button" = "Բարձրացնել";
"to_whom" = "Ում";
"increase_by" = "Բարձրացնել";
"price" = "Արժողություն";
"you_have_unused_votes" = "Ձեր մոտ $1 չօգտագործված ձայն կա հաշվի վրա։";
"apply_voucher" = "Կիրառել վաուչեր";
"failed_to_increase_rating" = "Չհաջողվե՛ց բարձրացնել վարկանիշը";
"rating_increase_successful" = "Դուք հաջողությամբ բարձրացրեցիք Ձեր վարկանիշը <b><a href=\"$1\">$2</a></b> <b>$3%</b>-ով։";
"negative_rating_value" = "Կներե՛ք, մենք չենք կարող գողանալ ուրիշի վարկանիշը։";
"increased_your_rating_by" = "բարձրացրել է վարկանիշը";
/* Gifts */
"gift" = "Նվեր";
@ -703,6 +722,9 @@
"ticket_changed" = "Տոմսը փոփոխված է";
"ticket_changed_comment" = "Փոփոխությունները ուժի մեջ կմտնեն մի քանի վայրկյանից։";
"banned_in_support_1" = "Կներե՛ք, <b>$1</b>, բայց հիմա Ձեզ թույլատրված չէ դիմումներ ստեղծել։";
"banned_in_support_2" = "Դրա պատճառաբանությունը սա է․ <b>$1</b>։ Ցավո՛ք, այդ հնարավորությունը մենք Ձեզնից վերցրել ենք առհավետ։";
/* Invite */
"invite" = "Հրավիրել";
@ -711,9 +733,9 @@
/* Banned */
"banned_title" = "Բլոկավորված եք";
"banned_header" = "Ձեզ կասեցրել է կառլենի անհաջող բոցը։";
"banned_alt" = "Օգտատերը բլոկավորված է";
"banned_title" = "Արգելափակված եք";
"banned_header" = "Ձեզ կասեցրել է կարլենի անհաջող բոցը։";
"banned_alt" = "Օգտատերը արգելափակված է";
"banned_1" = "Կներե՛ք, <b>$1</b>, բայց Դուք կասեցված եք։";
"banned_2" = "Պատճառը հետևյալն է․ <b>$1</b>. Ափսոս, բայց մենք ստիպված Ձեզ հավերժ ենք կասեցրել;";
"banned_3" = "Դուք դեռ կարող եք <a href=\"/support?act=new\">գրել նամակ աջակցության ծառայությանը</a>, եթե համարում եք որ դա սխալմունք է, կամ էլ կարող եք <a href=\"/logout?hash=$1\">դուրս գալ</a>։";
@ -835,6 +857,7 @@
"captcha_error" = "Սխալ են գրված սիմվոլները";
"captcha_error_comment" = "Խնդրում ենք համոզվել, որ ճիշտ եք ներմուծել կապտչայի սիմվոլները։";
/* Admin actions */
"login_as" = "Մտնել ինչպես $1";
@ -843,7 +866,84 @@
"ban_user_action" = "Բլոկավորել օգտվողին";
"warn_user_action" = "Զգուշացնել օգտվողին";
/* Paginator (subject to delete) */
/* Admin panel */
"admin" = "Ադմին-վահանակ";
"admin_ownerid" = "Տիրոջ ID";
"admin_author" = "Հեղինակ";
"admin_name" = "Անուն";
"admin_title" = "Անվանում";
"admin_description" = "Նկարագրություն";
"admin_first_known_ip" = "Առաջին IP";
"admin_shortcode" = "Կարճ հասցե";
"admin_verification" = "Վերիֆիկացիա";
"admin_banreason" = "Արգելափակման պատճառ";
"admin_banned" = "արգելափակված է";
"admin_actions" = "Գործողություններ";
"admin_image" = "Նկար";
"admin_image_replace" = "Փոխե՞լ նկարը";
"admin_uses" = "Օգտագործումներ";
"admin_uses_reset" = "Զրոյացնե՞լ օգտագործումների քանակը";
"admin_limits" = "Սահմանափակումներ";
"admin_limits_reset" = "Զրոյացնել օգտագործումների քանակը";
"admin_open" = "Բացել";
"admin_loginas" = "Մուտք գործել ինչպես...";
"admin_commonsettings" = "Ընդհանուր կարգավորումներ";
"admin_langsettings" = "Լեզվից կախված կարգավորումներ";
"admin_tab_main" = "Գլխավոր";
"admin_tab_ban" = "Բլոկավորում";
"admin_tab_followers" = "Մասնակիցներ";
"admin_overview" = "Դիտում";
"admin_overview_summary" = "Ամփոփում";
"admin_content" = "Օգտատիրային կոնտենտ";
"admin_user_search" = "Օգտատերերի որոնում";
"admin_user_online" = "Օնլայն վիճակ";
"admin_user_online_default" = "Ըստ նախնականի";
"admin_user_online_incognito" = "Ինկոգնիտո";
"admin_user_online_deceased" = "Հանգուցյալ";
"admin_club_search" = "Խմբերի որոնում";
"admin_club_excludeglobalfeed" = "Չ՛ցույց տալ գլոբալ ժապավենում";
"admin_services" = "Վճարովի ծառայություններ";
"admin_newgift" = "Նոր նվեր";
"admin_price" = "Գին";
"admin_giftset" = "Նվերների հավաքախու";
"admin_giftsets" = "Նվերների հավաքախուներ";
"admin_giftsets_none" = "Նվերների հավաքածու չկա։ Ստեղծե՛ք հավաքածու նվեր ավելացնելու համար։";
"admin_giftsets_create" = "Ստեղծել նվերների հավաքածու";
"admin_giftsets_title" = "Հավաքածույի ներքին անվանում, եթե չի հաջողվում որոնել այն օգտատիրոջ լեզվով";
"admin_giftsets_description" = "Հավաքածույի ներքին նկարագրություն, եթե չի հաջողվում որոնել այն օգտատիրոջ լեզվով";
"admin_price_free" = "անվճար";
"admin_voucher_rating" = "Վարկանիշ";
"admin_voucher_serial" = "Սերիական համար";
"admin_voucher_serial_desc" = "Համարը բաղկացած է 24 նշից։ Եթե Դուք այն սխալ գրեք, այն կտրվի ավտոմատ։";
"admin_voucher_coins" = "Ձայների քանակ";
"admin_voucher_rating" = "Վարկանշի քանակ";
"admin_voucher_usages_desc" = "Վաուչերը օգտագործող ակկաունտների քանակ։ Եթե գրեք -1, ապա այն կլինի օգտագործել անվերջ։";
"admin_voucher_status" = "Կարգավիճակ";
"admin_voucher_status_opened" = "ակտիվ է";
"admin_voucher_status_closed" = "վերջացել է";
"admin_settings" = "Կարգավորումներ";
"admin_settings_tuning" = "Ընդհանուր";
"admin_settings_appearance" = "Արտաքին տեսք";
"admin_settings_security" = "Անվտանգություն";
"admin_settings_integrations" = "Ինտեգրացիաներ";
"admin_settings_system" = "Համակարգ";
"admin_about" = "OpenVK-ի մասին";
"admin_about_version" = "Վերսիա";
"admin_about_instance" = "Հոսք";
"admin_commerce_disabled" = "Կոմմերցիան անջատված է համակարգային ադմինիստրատորի կողմից";
"admin_commerce_disabled_desc" = "Վաուչերների և նվերների կարգավորումները կպահպանվեն, բայց ոչ մի ազդեցություն չեն ունենա։";
/* Paginator (deprecated) */
"paginator_back" = "Հետ";
"paginator_page" = "$1 էջ";
@ -857,6 +957,8 @@
"rules" = "Կանոններ";
"most_popular_groups" = "Ամենահայտնի խմբերը";
"on_this_instance_are" = "Այս հոսքում․";
"about_links" = "Հղումներ";
"instance_links" = "Հոսքերի հղումներ․";
"about_users_one" = "<b>Մեկ</b> օգտատեր";
"about_users_few" = "<b>$1</b> օգտատեր";

View file

@ -444,6 +444,8 @@
"your_page_address" = "Your address page";
"page_address" = "Address page";
"current_email_address" = "Current email address";
"new_email_address" = "New email address";
"save_email_address" = "Save email address";
"page_id" = "Page ID";
"you_can_also" = "You can also";
"delete_your_page" = "delete your page";
@ -458,6 +460,8 @@
"additional_links" = "Additional links";
"ad_poster" = "Ad poster";
"email_change_confirm_message" = "Please confirm your new email address for the change to take effect. We have sent instructions to it.";
/* Two-factor authentication */
"two_factor_authentication" = "Two-factor authentication";

View file

@ -472,6 +472,8 @@
"your_page_address" = "Адрес Вашей страницы";
"page_address" = "Адрес страницы";
"current_email_address" = "Текущий адрес";
"new_email_address" = "Новый адрес";
"save_email_address" = "Сохранить адрес";
"page_id" = "ID страницы";
"you_can_also" = "Вы также можете";
"delete_your_page" = "удалить свою страницу";
@ -486,6 +488,8 @@
"additional_links" = "Дополнительные ссылки";
"ad_poster" = "Рекламный плакат";
"email_change_confirm_message" = "Чтобы изменение вступило в силу, подтвердите ваш новый адрес электронной почты. Мы отправили инструкции на него.";
/* Two-factor authentication */
"two_factor_authentication" = "Двухфакторная аутентификация";