mirror of
https://github.com/openvk/openvk
synced 2024-12-22 16:42:32 +03:00
parent
245f8690c6
commit
14d5caaf9f
7 changed files with 442 additions and 57 deletions
|
@ -27,7 +27,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
if(!$user) $this->notFound();
|
||||
if (!$user->getPrivacyPermission('photos.read', $this->user->identity ?? NULL))
|
||||
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
|
||||
$this->template->albums = $this->albums->getUserAlbums($user, $this->queryParam("p") ?? 1);
|
||||
$this->template->albums = $this->albums->getUserAlbums($user, (int)($this->queryParam("p") ?? 1));
|
||||
$this->template->count = $this->albums->getUserAlbumsCount($user);
|
||||
$this->template->owner = $user;
|
||||
$this->template->canEdit = false;
|
||||
|
@ -36,7 +36,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
} else {
|
||||
$club = (new Clubs)->get(abs($owner));
|
||||
if(!$club) $this->notFound();
|
||||
$this->template->albums = $this->albums->getClubAlbums($club, $this->queryParam("p") ?? 1);
|
||||
$this->template->albums = $this->albums->getClubAlbums($club, (int)($this->queryParam("p") ?? 1));
|
||||
$this->template->count = $this->albums->getClubAlbumsCount($club);
|
||||
$this->template->owner = $club;
|
||||
$this->template->canEdit = false;
|
||||
|
@ -46,7 +46,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
|
||||
$this->template->paginatorConf = (object) [
|
||||
"count" => $this->template->count,
|
||||
"page" => $this->queryParam("p") ?? 1,
|
||||
"page" => (int)($this->queryParam("p") ?? 1),
|
||||
"amount" => NULL,
|
||||
"perPage" => OPENVK_DEFAULT_PER_PAGE,
|
||||
];
|
||||
|
@ -147,7 +147,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
$this->template->photos = iterator_to_array( $album->getPhotos( (int) ($this->queryParam("p") ?? 1), 20) );
|
||||
$this->template->paginatorConf = (object) [
|
||||
"count" => $album->getPhotosCount(),
|
||||
"page" => $this->queryParam("p") ?? 1,
|
||||
"page" => (int)($this->queryParam("p") ?? 1),
|
||||
"amount" => sizeof($this->template->photos),
|
||||
"perPage" => 20,
|
||||
"atBottom" => true
|
||||
|
@ -221,39 +221,74 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
function renderUploadPhoto(): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
$this->willExecuteWriteAction();
|
||||
$this->willExecuteWriteAction(true);
|
||||
|
||||
if(is_null($this->queryParam("album")))
|
||||
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в <b>DELETED</b>.");
|
||||
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в DELETED.", 500, true);
|
||||
|
||||
[$owner, $id] = explode("_", $this->queryParam("album"));
|
||||
$album = $this->albums->get((int) $id);
|
||||
if(!$album)
|
||||
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в <b>DELETED</b>.");
|
||||
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в DELETED.", 500, true);
|
||||
if(is_null($this->user) || !$album->canBeModifiedBy($this->user->identity))
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.");
|
||||
$this->flashFail("err", "Ошибка доступа", "Недостаточно прав для модификации данного ресурса.", 500, true);
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
if(!isset($_FILES["blob"]))
|
||||
$this->flashFail("err", "Нету фотографии", "Выберите файл.");
|
||||
if($this->queryParam("act") == "finish") {
|
||||
$result = json_decode($this->postParam("photos"), true);
|
||||
|
||||
foreach($result as $photoId => $description) {
|
||||
$phot = $this->photos->get($photoId);
|
||||
|
||||
if(!$phot || $phot->isDeleted() || $phot->getOwner()->getId() != $this->user->id)
|
||||
continue;
|
||||
|
||||
if(iconv_strlen($description) > 255)
|
||||
$this->flashFail("err", tr("error"), tr("description_too_long"), 500, true);
|
||||
|
||||
$phot->setDescription($description);
|
||||
$phot->save();
|
||||
|
||||
$album = $phot->getAlbum();
|
||||
}
|
||||
|
||||
$this->returnJson(["success" => true,
|
||||
"album" => $album->getId(),
|
||||
"owner" => $album->getOwner() instanceof User ? $album->getOwner()->getId() : $album->getOwner()->getId() * -1]);
|
||||
}
|
||||
|
||||
if(!isset($_FILES))
|
||||
$this->flashFail("err", "Нету фотографии", "Выберите файл.", 500, true);
|
||||
|
||||
$photos = [];
|
||||
for($i = 0; $i < $this->postParam("count"); $i++) {
|
||||
try {
|
||||
$photo = new Photo;
|
||||
$photo->setOwner($this->user->id);
|
||||
$photo->setDescription($this->postParam("desc"));
|
||||
$photo->setFile($_FILES["blob"]);
|
||||
$photo->setDescription("");
|
||||
$photo->setFile($_FILES["photo_".$i]);
|
||||
$photo->setCreated(time());
|
||||
$photo->save();
|
||||
|
||||
$photos[] = [
|
||||
"url" => $photo->getURLBySizeId("tiny"),
|
||||
"id" => $photo->getId(),
|
||||
"vid" => $photo->getVirtualId(),
|
||||
"owner" => $photo->getOwner()->getId(),
|
||||
"link" => $photo->getURL()
|
||||
];
|
||||
} catch(ISE $ex) {
|
||||
$name = $album->getName();
|
||||
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в <b>$name</b>.");
|
||||
$this->flashFail("err", "Неизвестная ошибка", "Не удалось сохранить фотографию в $name.", 500, true);
|
||||
}
|
||||
|
||||
$album->addPhoto($photo);
|
||||
$album->setEdited(time());
|
||||
$album->save();
|
||||
}
|
||||
|
||||
$this->redirect("/photo" . $photo->getPrettyId() . "?from=album" . $album->getId());
|
||||
$this->returnJson(["success" => true,
|
||||
"photos" => $photos]);
|
||||
} else {
|
||||
$this->template->album = $album;
|
||||
}
|
||||
|
@ -285,7 +320,7 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
function renderDeletePhoto(int $ownerId, int $photoId): void
|
||||
{
|
||||
$this->assertUserLoggedIn();
|
||||
$this->willExecuteWriteAction();
|
||||
$this->willExecuteWriteAction($_SERVER["REQUEST_METHOD"] === "POST");
|
||||
$this->assertNoCSRF();
|
||||
|
||||
$photo = $this->photos->getByOwnerAndVID($ownerId, $photoId);
|
||||
|
@ -298,6 +333,9 @@ final class PhotosPresenter extends OpenVKPresenter
|
|||
$photo->isolate();
|
||||
$photo->delete();
|
||||
|
||||
if($_SERVER["REQUEST_METHOD"] === "POST")
|
||||
$this->returnJson(["success" => true]);
|
||||
|
||||
$this->flash("succ", "Фотография удалена", "Эта фотография была успешно удалена.");
|
||||
$this->redirect($redirect);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,15 @@
|
|||
{/block}
|
||||
|
||||
{block content}
|
||||
<div class="tabs">
|
||||
<div id="activetabs" class="tab">
|
||||
<a id="act_tab_a" href="/album{$album->getPrettyId()}/edit">{_edit_album}</a>
|
||||
</div>
|
||||
<div class="tab">
|
||||
<a href="/photos/upload?album={$album->getPrettyId()}">{_add_photos}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<table cellspacing="6">
|
||||
<tbody>
|
||||
|
|
|
@ -12,32 +12,53 @@
|
|||
{/block}
|
||||
|
||||
{block content}
|
||||
<form action="/photos/upload?album={$album->getPrettyId()}" method="post" enctype="multipart/form-data">
|
||||
<table cellspacing="6">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_description}:</span></td>
|
||||
<td><textarea style="margin: 0px; height: 50px; width: 159px; resize: none;" name="desc"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"><span class="nobold">{_photo}:</span></td>
|
||||
<td>
|
||||
<label class="button" style="">{_browse}
|
||||
<input type="file" id="blob" name="blob" style="display: none;" onchange="filename.innerHTML=blob.files[0].name" />
|
||||
</label>
|
||||
<div id="filename" style="margin-top: 10px;"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="120" valign="top"></td>
|
||||
<td>
|
||||
<input type="hidden" name="hash" value="{$csrfToken}" />
|
||||
<input type="submit" class="button" name="submit" value="Загрузить" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="tabs">
|
||||
<div class="tab">
|
||||
<a href="/album{$album->getPrettyId()}/edit">{_edit_album}</a>
|
||||
</div>
|
||||
<div id="activetabs" class="tab">
|
||||
<a id="act_tab_a" href="#">{_add_photos}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input n:ifset="$_GET['album']" type="hidden" name="album" value="{$_GET['album']}" />
|
||||
</form>
|
||||
<input type="file" accept=".jpg,.png,.gif" name="files[]" multiple class="button" id="uploadButton" style="display:none">
|
||||
|
||||
<div class="container_gray" style="height: 344px;">
|
||||
<div class="insertThere"></div>
|
||||
<div class="whiteBox" style="display: block;">
|
||||
<div class="boxContent">
|
||||
<h4>{_uploading_photos_from_computer}</h4>
|
||||
|
||||
<div class="limits" style="margin-top:17px">
|
||||
<b style="color:#45688E">{_admin_limits}</b>
|
||||
<ul class="blueList" style="margin-left: -25px;margin-top: 1px;">
|
||||
<li>{_supported_formats}</li>
|
||||
<li>{_max_load_photos}</li>
|
||||
</ul>
|
||||
|
||||
<div style="text-align: center;padding-top: 4px;" class="insertAgain">
|
||||
<input type="button" class="button" id="fakeButton" onclick="uploadButton.click()" value="{_upload_picts}">
|
||||
</div>
|
||||
|
||||
<div class="tipping" style="margin-top: 19px;">
|
||||
<span style="line-height: 15px"><b>{_tip}</b>: {_tip_ctrl}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="insertPhotos" id="photos" style="margin-top: 9px;padding-bottom: 12px;"></div>
|
||||
|
||||
<input type="button" class="button" style="display:none;margin-left: auto;margin-right: auto;" id="endUploading" value="{_end_uploading}">
|
||||
</div>
|
||||
|
||||
<input n:ifset="$_GET['album']" type="hidden" id="album" value="{$_GET['album']}" />
|
||||
|
||||
<script>
|
||||
uploadButton.value = ''
|
||||
</script>
|
||||
{/block}
|
||||
|
||||
{block bodyScripts}
|
||||
{script "js/al_photos.js"}
|
||||
{/block}
|
||||
|
|
|
@ -2701,3 +2701,99 @@ body.article .floating_sidebar, body.article .page_content {
|
|||
right: 22px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.uploadedImage img {
|
||||
max-height: 76px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.lagged {
|
||||
filter: opacity(0.5);
|
||||
cursor: progress;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.lagged * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.button.dragged {
|
||||
background: #c4c4c4 !important;
|
||||
border-color: #c4c4c4 !important;
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.whiteBox {
|
||||
background: white;
|
||||
width: 421px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border: 1px solid #E8E8E8;
|
||||
margin-top: 7%;
|
||||
height: 231px;
|
||||
}
|
||||
|
||||
.boxContent {
|
||||
padding: 24px 38px;
|
||||
}
|
||||
|
||||
.blueList {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.blueList li {
|
||||
color: black;
|
||||
font-size: 11px;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
.blueList li::before {
|
||||
content: " ";
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
background-color: #73889C;
|
||||
margin: 3px;
|
||||
margin-left: 2px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
|
||||
.insertedPhoto {
|
||||
background: white;
|
||||
border: 1px solid #E8E7EA;
|
||||
padding: 10px;
|
||||
height: 100px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.uploadedImage {
|
||||
float: right;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uploadedImageDescription {
|
||||
width: 449px;
|
||||
}
|
||||
|
||||
.uploadedImageDescription textarea {
|
||||
width: 84%;
|
||||
height: 86px;
|
||||
}
|
||||
|
||||
.smallFrame {
|
||||
border: 1px solid #E1E3E5;
|
||||
background: #F0F0F0;
|
||||
height: 33px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.smallFrame .smallBtn {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.smallFrame:hover {
|
||||
background: #E9F0F1 !important;
|
||||
}
|
||||
|
|
179
Web/static/js/al_photos.js
Normal file
179
Web/static/js/al_photos.js
Normal file
|
@ -0,0 +1,179 @@
|
|||
$(document).on("change", "#uploadButton", (e) => {
|
||||
let iterator = 0
|
||||
|
||||
if(e.currentTarget.files.length > 10) {
|
||||
MessageBox(tr("error"), tr("too_many_pictures"), [tr("ok")], [() => {Function.noop}])
|
||||
return;
|
||||
}
|
||||
|
||||
if(document.querySelector(".whiteBox").style.display == "block") {
|
||||
document.querySelector(".whiteBox").style.display = "none"
|
||||
document.querySelector(".insertThere").append(document.getElementById("fakeButton"));
|
||||
}
|
||||
|
||||
let photos = new FormData()
|
||||
for(file of e.currentTarget.files) {
|
||||
photos.append("photo_"+iterator, file)
|
||||
iterator += 1
|
||||
}
|
||||
|
||||
photos.append("count", e.currentTarget.files.length)
|
||||
photos.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
|
||||
let xhr = new XMLHttpRequest()
|
||||
xhr.open("POST", "/photos/upload?album="+document.getElementById("album").value)
|
||||
|
||||
xhr.onloadstart = () => {
|
||||
document.querySelector(".insertPhotos").insertAdjacentHTML("beforeend", `<img id="loader" src="/assets/packages/static/openvk/img/loading_mini.gif">`)
|
||||
}
|
||||
|
||||
xhr.onload = () => {
|
||||
let result = JSON.parse(xhr.responseText)
|
||||
|
||||
if(result.success) {
|
||||
u("#loader").remove()
|
||||
let photosArr = result.photos
|
||||
|
||||
for(photo of photosArr) {
|
||||
let table = document.querySelector(".insertPhotos")
|
||||
|
||||
table.insertAdjacentHTML("beforeend", `
|
||||
<div id="photo" class="insertedPhoto" data-id="${photo.id}">
|
||||
<div class="uploadedImageDescription" style="float: left;">
|
||||
<span style="color: #464646;position: absolute;">${tr("description")}:</span>
|
||||
<textarea style="margin-left: 62px; resize: none;" maxlength="255"></textarea>
|
||||
</div>
|
||||
<div class="uploadedImage">
|
||||
<a href="${photo.link}" target="_blank"><img width="125" src="${photo.url}"></a>
|
||||
<a class="profile_link" style="width: 125px;" id="deletePhoto" data-id="${photo.vid}" data-owner="${photo.owner}">${tr("delete")}</a>
|
||||
<!--<div class="smallFrame" style="margin-top: 6px;">
|
||||
<div class="smallBtn">${tr("album_poster")}</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
`)
|
||||
}
|
||||
|
||||
document.getElementById("endUploading").style.display = "block"
|
||||
} else {
|
||||
u("#loader").remove()
|
||||
MessageBox(tr("error"), escapeHtml(result.flash.message) ?? tr("error_uploading_photo"), [tr("ok")], [() => {Function.noop}])
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(photos)
|
||||
})
|
||||
|
||||
$(document).on("click", "#endUploading", (e) => {
|
||||
let table = document.querySelector("#photos")
|
||||
let data = new FormData()
|
||||
let arr = new Map();
|
||||
for(el of table.querySelectorAll("div#photo")) {
|
||||
arr.set(el.dataset.id, el.querySelector("textarea").value)
|
||||
}
|
||||
|
||||
data.append("photos", JSON.stringify(Object.fromEntries(arr)))
|
||||
data.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
|
||||
let xhr = new XMLHttpRequest()
|
||||
// в самом вк на каждое изменение описания отправляется свой запрос, но тут мы экономим запросы
|
||||
xhr.open("POST", "/photos/upload?act=finish&album="+document.getElementById("album").value)
|
||||
|
||||
xhr.onloadstart = () => {
|
||||
e.currentTarget.setAttribute("disabled", "disabled")
|
||||
}
|
||||
|
||||
xhr.onerror = () => {
|
||||
MessageBox(tr("error"), tr("error_uploading_photo"), [tr("ok")], [() => {Function.noop}])
|
||||
}
|
||||
|
||||
xhr.onload = () => {
|
||||
let result = JSON.parse(xhr.responseText)
|
||||
|
||||
if(!result.success) {
|
||||
MessageBox(tr("error"), escapeHtml(result.flash.message), [tr("ok")], [() => {Function.noop}])
|
||||
} else {
|
||||
document.querySelector(".page_content .insertPhotos").innerHTML = ""
|
||||
document.getElementById("endUploading").style.display = "none"
|
||||
|
||||
NewNotification(tr("photos_successfully_uploaded"), tr("click_to_go_to_album"), null, () => {window.location.assign(`/album${result.owner}_${result.album}`)})
|
||||
|
||||
document.querySelector(".whiteBox").style.display = "block"
|
||||
document.querySelector(".insertAgain").append(document.getElementById("fakeButton"))
|
||||
}
|
||||
|
||||
e.currentTarget.removeAttribute("disabled")
|
||||
}
|
||||
|
||||
xhr.send(data)
|
||||
})
|
||||
|
||||
$(document).on("click", "#deletePhoto", (e) => {
|
||||
let data = new FormData()
|
||||
data.append("hash", u("meta[name=csrf]").attr("value"))
|
||||
|
||||
let xhr = new XMLHttpRequest()
|
||||
xhr.open("POST", `/photo${e.currentTarget.dataset.owner}_${e.currentTarget.dataset.id}/delete`)
|
||||
|
||||
xhr.onloadstart = () => {
|
||||
e.currentTarget.closest("div#photo").classList.add("lagged")
|
||||
}
|
||||
|
||||
xhr.onerror = () => {
|
||||
MessageBox(tr("error"), tr("unknown_error"), [tr("ok")], [() => {Function.noop}])
|
||||
}
|
||||
|
||||
xhr.onload = () => {
|
||||
u(e.currentTarget.closest("div#photo")).remove()
|
||||
|
||||
if(document.querySelectorAll("div#photo").length < 1) {
|
||||
document.getElementById("endUploading").style.display = "none"
|
||||
document.querySelector(".whiteBox").style.display = "block"
|
||||
document.querySelector(".insertAgain").append(document.getElementById("fakeButton"))
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(data)
|
||||
})
|
||||
|
||||
$(document).on("dragover drop", (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
return false;
|
||||
})
|
||||
|
||||
$(document).on("dragover", (e) => {
|
||||
e.preventDefault()
|
||||
document.querySelector("#fakeButton").classList.add("dragged")
|
||||
document.querySelector("#fakeButton").value = tr("drag_files_here")
|
||||
})
|
||||
|
||||
$(document).on("dragleave", (e) => {
|
||||
e.preventDefault()
|
||||
document.querySelector("#fakeButton").classList.remove("dragged")
|
||||
document.querySelector("#fakeButton").value = tr("upload_picts")
|
||||
})
|
||||
|
||||
$("#fakeButton").on("drop", (e) => {
|
||||
e.originalEvent.dataTransfer.dropEffect = 'move';
|
||||
e.preventDefault()
|
||||
|
||||
$(document).trigger("dragleave")
|
||||
|
||||
let files = e.originalEvent.dataTransfer.files
|
||||
|
||||
for(const file of files) {
|
||||
if(!file.type.startsWith('image/')) {
|
||||
MessageBox(tr("error"), tr("only_images_accepted", escapeHtml(file.name)), [tr("ok")], [() => {Function.noop}])
|
||||
return;
|
||||
}
|
||||
|
||||
if(file.size > 5 * 1024 * 1024) {
|
||||
MessageBox(tr("error"), tr("max_filesize", 5), [tr("ok")], [() => {Function.noop}])
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("uploadButton").files = files
|
||||
u("#uploadButton").trigger("change")
|
||||
})
|
|
@ -381,6 +381,25 @@
|
|||
"upd_f" = "updated her profile picture";
|
||||
"upd_g" = "updated group's picture";
|
||||
|
||||
"add_photos" = "Add photos";
|
||||
"upload_picts" = "Upload photos";
|
||||
"end_uploading" = "Finish uploading";
|
||||
"photos_successfully_uploaded" = "Photos successfully uploaded";
|
||||
"click_to_go_to_album" = "Click here to go to album.";
|
||||
"error_uploading_photo" = "Error when uploading photo";
|
||||
"too_many_pictures" = "No more than 10 pictures";
|
||||
|
||||
"drag_files_here" = "Drag files here";
|
||||
"only_images_accepted" = "File \"$1\" is not an image";
|
||||
"max_filesize" = "Max filesize is $1 MB";
|
||||
|
||||
"uploading_photos_from_computer" = "Uploading photos from Your computer";
|
||||
"supported_formats" = "Supported file formats: JPG, PNG and GIF.";
|
||||
"max_load_photos" = "You can upload up to 10 photos at a time.";
|
||||
"tip" = "Tip";
|
||||
"tip_ctrl" = "to select multiple photos at once, hold down the Ctrl key when selecting files in Windows or the CMD key in Mac OS.";
|
||||
"album_poster" = "Album poster";
|
||||
|
||||
/* Notes */
|
||||
|
||||
"notes" = "Notes";
|
||||
|
@ -1066,6 +1085,7 @@
|
|||
"error_data_too_big" = "Attribute '$1' must be at most $2 $3 long";
|
||||
|
||||
"forbidden" = "Access error";
|
||||
"unknown_error" = "Unknown error";
|
||||
"forbidden_comment" = "This user's privacy settings do not allow you to look at his page.";
|
||||
|
||||
"changes_saved" = "Changes saved";
|
||||
|
@ -1117,6 +1137,7 @@
|
|||
"media_file_corrupted_or_too_large" = "The media content file is corrupted or too large.";
|
||||
"post_is_empty_or_too_big" = "The post is empty or too big.";
|
||||
"post_is_too_big" = "The post is too big.";
|
||||
"description_too_long" = "Description is too long.";
|
||||
|
||||
/* Admin actions */
|
||||
|
||||
|
|
|
@ -364,6 +364,25 @@
|
|||
"upd_f" = "обновила фотографию на своей странице";
|
||||
"upd_g" = "обновило фотографию группы";
|
||||
|
||||
"add_photos" = "Добавить фотографии";
|
||||
"upload_picts" = "Загрузить фотографии";
|
||||
"end_uploading" = "Завершить загрузку";
|
||||
"photos_successfully_uploaded" = "Фотографии успешно загружены";
|
||||
"click_to_go_to_album" = "Нажмите, чтобы перейти к альбому.";
|
||||
"error_uploading_photo" = "Не удалось загрузить фотографию";
|
||||
"too_many_pictures" = "Не больше 10 фотографий";
|
||||
|
||||
"drag_files_here" = "Перетащите файлы сюда";
|
||||
"only_images_accepted" = "Файл \"$1\" не является изображением";
|
||||
"max_filesize" = "Максимальный размер файла — $1 мегабайт";
|
||||
|
||||
"uploading_photos_from_computer" = "Загрузка фотографий с Вашего компьютера";
|
||||
"supported_formats" = "Поддерживаемые форматы файлов: JPG, PNG и GIF.";
|
||||
"max_load_photos" = "Вы можете загружать до 10 фотографий за один раз.";
|
||||
"tip" = "Подсказка";
|
||||
"tip_ctrl" = "для того, чтобы выбрать сразу несколько фотографий, удерживайте клавишу Ctrl при выборе файлов в ОС Windows или клавишу CMD в Mac OS.";
|
||||
"album_poster" = "Обложка альбома";
|
||||
|
||||
/* Notes */
|
||||
|
||||
"notes" = "Заметки";
|
||||
|
@ -982,6 +1001,7 @@
|
|||
"error_repost_fail" = "Не удалось поделиться записью";
|
||||
"error_data_too_big" = "Аттрибут '$1' не может быть длиннее $2 $3";
|
||||
"forbidden" = "Ошибка доступа";
|
||||
"unknown_error" = "Неизвестная ошибка";
|
||||
"forbidden_comment" = "Настройки приватности этого пользователя не разрешают вам смотреть на его страницу.";
|
||||
"changes_saved" = "Изменения сохранены";
|
||||
"changes_saved_comment" = "Новые данные появятся на вашей странице";
|
||||
|
@ -1017,6 +1037,7 @@
|
|||
"media_file_corrupted_or_too_large" = "Файл медиаконтента повреждён или слишком велик.";
|
||||
"post_is_empty_or_too_big" = "Пост пустой или слишком большой.";
|
||||
"post_is_too_big" = "Пост слишком большой.";
|
||||
"description_too_long" = "Описание слишком длинное.";
|
||||
|
||||
/* Admin actions */
|
||||
|
||||
|
|
Loading…
Reference in a new issue