Compare commits

...

236 commits
v0.5.4 ... main

Author SHA1 Message Date
Evg
f04ed28a30 FIX: Пагинация в каталоге
+ улучшение rtl и др. в css.
2023-11-22 06:03:21 +03:00
Evg
0d4075ada9 ADD: class DetectMobile
+ коррекция Ночного режима.
2023-11-21 03:56:49 +03:00
Evg
a179dde10b UX: Ссылка на якорь при фикс. шапке
См. https://libarea.ru/post/1604/testovyy-post-migraciya-kommentariev
2023-11-20 12:37:04 +03:00
Evg
40f9345ea4 DEV: Объединение Ответов и Комментариев
См. https://libarea.ru/post/1604/testovyy-post-migraciya-kommentariev
2023-11-20 03:24:46 +03:00
Evg
cbfba207a3 DEV: Локализация 2023-11-18 03:54:05 +03:00
Evg
2e96b09e8d FIX: BuildTree
+ улучшение Ночной темы...
2023-11-17 08:55:03 +03:00
Evg
612b5ed1c9 EDIT: BuildTree.php 2023-11-15 11:48:04 +03:00
Evg
c1e5813a33 UPDATE: PrismJS 1.29.0 2023-11-15 04:01:35 +03:00
Evg
f09ce2e3f2 DEV: Форматирование css, js (по Codacy) 2023-11-14 08:23:49 +03:00
Evg
354ee060c4 DEV: Незначительные изменения (css) 2023-11-14 04:49:48 +03:00
Evg
cd75d483d8 FIX: Комментарии (каталог)
+ упростим CSS
2023-11-13 09:46:32 +03:00
Evg
5d61d8827f FIX: Скролл в ленте
+ UX: высота редактора в посте.
2023-11-10 05:05:22 +03:00
Evg
87bf2b0183 DEV: Незначительные изменения (css) 2023-11-09 04:56:40 +03:00
Evg
9ccdd14bf5 EDIT: Темная тема (css) 2023-11-08 09:39:22 +03:00
Evg
19d882395d DEV: Структура css
Для возможности сборки не средствами PHP (- Minify)...
2023-11-08 07:58:49 +03:00
Evg
dfd3e8edaf UX: Сортировка участников 2023-11-05 03:49:34 +03:00
Evg
73c0d65254 DEV: Незначительные изменения (css) 2023-11-04 02:33:49 +03:00
Evg
5e099601f7 FIX: Переключение комментариев 2023-11-03 08:09:33 +03:00
Evg
348a44d0ea DEV: Вынесем function buildTree
Необходимо для модулей, плагинов и т.д.
2023-11-03 05:28:13 +03:00
Evg
01676e92e0 DEV: Упорядочивание css (4 часть) 2023-11-03 05:15:43 +03:00
Evg
c42e9e9326 DEV: Упорядочивание css (3 часть)
+ Update site-off.php
https://github.com/LibArea/libarea/pull/30
2023-10-31 17:57:20 +03:00
Evg
ef2d2cc2ad
Merge pull request #30 from sergeevizh/patch-1
Update site-off.php
2023-10-31 17:42:55 +03:00
Kirill Trubetskoy
921c5c946d
Update site-off.php
Добавлен текущий год в футер и изменен заголовок c "Opss" на "Режим технического обслуживания".
2023-10-31 17:01:58 +03:00
Evg
4ac3181651 DEV: Упорядочивание css (2 часть) 2023-10-31 05:00:27 +03:00
Evg
a115dc4693 ADD: Запрет комментариев из Фасета (глобальный)
См. https://libarea.ru/post/1569/allow-admins-to-close-spicfic-to-prevent-the-users-from-posting-comments-on-the-posts
2023-10-30 06:26:30 +03:00
Evg
aa49b0cf12 DEV: Упорядочивание css (1 часть) 2023-10-29 19:32:20 +03:00
Evg
9ec0d1d446 FIX: favicons в результатах поиска 2023-10-27 04:16:03 +03:00
Evg
107caa7b42 UX: Локализация 2023-10-26 05:21:19 +03:00
Evg
bb11da9290 DEV: Шаблон Light (css) 2023-10-25 04:40:09 +03:00
Evg
c79816deb6 DEV: css nickname
См. https://libarea.ru/post/1564/dev-dobavil-globalno-nickname
2023-10-23 18:56:00 +03:00
Evg
8bf20137e0 UX: Комментарии в профиле 2023-10-21 16:40:13 +03:00
Evg
20ff9885f6 DEV: Локализация 2023-10-20 04:14:18 +03:00
Evg
415fc47cb5 DEV: Упростим контроллер 2023-10-19 03:38:52 +03:00
Evg
59b3c5be08 FIX: Админ-панель (SLUG ссылки)
+ коррекция дизайна Light.
2023-10-18 04:56:30 +03:00
Evg
11a0896327 ADD: Шаблон Light
+ упростим добавление.
См. https://libarea.ru/post/1557/kak-sozdat-svoy-shablon-dlya-libarea
2023-10-17 11:14:48 +03:00
Evg
59989d29d4 DEV: Выбор в профиле шаблона
Мы можем избежать (при новом шаблоне) внесения изменений в файлы локализации.
2023-10-09 19:00:32 +03:00
Evg
163ff67de3 DEV: Незначительные изменения 2023-10-09 18:28:19 +03:00
Evg
3ed6109aef DEV: Локализация 2023-10-06 19:56:31 +03:00
Evg
c9d1d10f73 DEV: Локализация 2023-10-06 04:25:01 +03:00
Evg
df5fec9192 FIX: Личные сообщения 2023-10-04 04:29:38 +03:00
Evg
182bf08f96 DEV: Незначительные изменения 2023-10-02 06:09:27 +03:00
Evg
45e79d5eb7 FIX: Прочитано 2023-09-30 20:52:21 +03:00
Evg
5799330a3e DEV: Незначительные изменения (css) 2023-09-30 06:12:56 +03:00
Evg
99eb130866 FIX: Доступ к Посту по ссылке
См. https://libarea.ru/post/1541/add-dostup-po-ssylke#answer_3024
2023-09-27 05:22:14 +03:00
Evg
8844eca665 FIX: Доступ к Посту по ссылке
См. https://libarea.ru/post/1541/add-dostup-po-ssylke
2023-09-26 19:54:05 +03:00
Evg
b94879f6bb ADD: Доступ по ссылке
См. https://libarea.ru/post/1541/add-dostup-po-ssylke
2023-09-26 05:34:24 +03:00
Evg
2ea9d307c0 DEV: Незначительные изменения (локализация) 2023-09-24 19:46:07 +03:00
Evg
f149752e29 DEV: Локализация 2023-09-24 19:38:55 +03:00
Evg
4277f392f9 DEV: Показ выбора голосования
+ аватар в профиле (моб. версия)
См. https://libarea.ru/post/1536/voprosy-po-fasetam-golosovaniyam-i-t-d
2023-09-21 03:43:40 +03:00
Evg
82497dbfa2 FIX: Запрет показ удаленных Фасетов 2023-09-18 03:52:59 +03:00
Evg
72d7bfc861 FIX: RTL (профиль) 2023-09-17 04:54:29 +03:00
Evg
705817ac25 DEV: Упростим css 2023-09-15 04:45:49 +03:00
Evg
c38901ee36 FIX: RTL (css) 2023-09-14 04:30:39 +03:00
Evg
8318ef9041 DEV: Упростим (adding a new language) 2023-09-13 06:07:33 +03:00
Evg
8c6c5dd762 ADD: Локализация (Вьетнам) 2023-09-12 06:23:54 +03:00
Evg
bf5f6b6d8a
Merge pull request #29 from saosangmo/main
Add Vietnamese Language
2023-09-12 05:43:55 +03:00
Dzung Do
4797a3cca3
Update admin.php 2023-09-12 01:41:57 +07:00
Dzung Do
358c5edc99
Update help.php 2023-09-12 00:49:28 +07:00
Dzung Do
301d053c93
Update web.php 2023-09-12 00:45:41 +07:00
Dzung Do
2f42400530
Update search.php 2023-09-12 00:44:47 +07:00
Dzung Do
c9bc6505ad
Update msg.php 2023-09-12 00:44:13 +07:00
Dzung Do
8a93d37491
Update msg.php 2023-09-12 00:43:39 +07:00
Dzung Do
e72e6a455b
Update meta.php 2023-09-12 00:43:25 +07:00
Dzung Do
37b9699e97
Update mail.php 2023-09-12 00:43:13 +07:00
Dzung Do
d622ac3c82
Update help.php 2023-09-12 00:43:01 +07:00
Dzung Do
12e4a91b31
Update app.php 2023-09-12 00:39:55 +07:00
Dzung Do
178093c731
Update app.php 2023-09-12 00:39:36 +07:00
Dzung Do
35341cd6a4
Update abbreviations.php 2023-09-12 00:38:04 +07:00
Dzung Do
b76360076a
Update 404.php 2023-09-12 00:35:41 +07:00
Dzung Do
6eb2d82763
Update app.php 2023-09-12 00:35:18 +07:00
Dzung Do
ae0c5f0d29
Update app.php 2023-09-10 01:24:36 +07:00
Dzung Do
51636c1f89
Update app.php 2023-09-10 01:02:31 +07:00
Dzung Do
1104ade934
Update web.php 2023-09-10 00:48:51 +07:00
Dzung Do
95913cdb1c
Update web.php 2023-09-10 00:43:26 +07:00
Dzung Do
dbfaebaf59
Update web.php 2023-09-10 00:40:43 +07:00
Dzung Do
dda9b7e18c
Update web.php 2023-09-10 00:36:01 +07:00
Dzung Do
61fd979280
Update app.php 2023-09-10 00:14:31 +07:00
Dzung Do
58d7bf1832
Create help.php 2023-09-10 00:07:54 +07:00
Dzung Do
231b6dbc0b
Create admin.php 2023-09-10 00:07:10 +07:00
Dzung Do
0d316cc007
Create web.php 2023-09-10 00:04:37 +07:00
Dzung Do
aa9ac9421d
Create abbreviations.php 2023-09-10 00:01:21 +07:00
Dzung Do
5a1749cdce
Create meta.php 2023-09-10 00:00:22 +07:00
Dzung Do
9ebfff80cd
Create auth.php 2023-09-09 23:56:17 +07:00
Dzung Do
4c7735b5e1
Create mail.php 2023-09-09 23:54:00 +07:00
Dzung Do
85a625198b
Update search.php 2023-09-09 23:50:45 +07:00
Dzung Do
ae98ade3e4
Create search.php 2023-09-09 23:48:16 +07:00
Dzung Do
76049ea219
Create off.php 2023-09-09 23:47:39 +07:00
Dzung Do
7abbddd9f7
Update app.php 2023-09-09 23:45:06 +07:00
Dzung Do
73a3b1e724
Merge branch 'LibArea:main' into main 2023-09-09 02:12:05 +07:00
Evg
f215b54f18 UX: Комментарии 2023-09-08 06:53:25 +03:00
Evg
cd2e2d2146 FIX: Ошибка в шаблоне 2023-09-08 05:34:50 +03:00
Evg
edaf9402a6 FIX: Рекомендованные темы (+ описание)
И упростим css (shadow)
2023-09-08 05:31:35 +03:00
Dzung Do
731c4bc505
Update app.php 2023-09-07 17:48:25 +07:00
Dzung Do
596f79645c
Create msg.php 2023-09-07 11:42:02 +07:00
Dzung Do
27f958ef2a
Create app.php 2023-09-07 11:41:17 +07:00
Dzung Do
a643a1bc8c
Update 404.php 2023-09-07 11:37:55 +07:00
Dzung Do
6bbaa902f5
Create 404.php 2023-09-07 11:36:38 +07:00
Evg
040ae18bba UX: Связанные посты
См. https://libarea.ru/post/1523/davayte-porabotaem-nad-podvalom-posta
2023-09-03 06:09:13 +03:00
Evg
d3dd286880 UX: Пост
См. https://libarea.ru/post/1523/davayte-porabotaem-nad-podvalom-posta
2023-09-02 07:37:42 +03:00
Evg
4a3f5503e4 UX: Незначительные изменения (css) 2023-08-25 03:25:22 +03:00
Evg
aa18093e9a DEV: Незначительные изменения (css) 2023-08-24 13:35:10 +03:00
Evg
55beb08240 DEV: Мобильная версия (border-radius)
См. https://libarea.ru/post/1507/nachal-peredelyvat-mobilnuyu-versiyu-libarea-i-dr#answer_2944
2023-08-22 20:06:56 +03:00
Evg
4af58f43c3 ADD: Работа с API stopforumspam.com 2023-08-18 04:19:45 +03:00
Evg
53be54faad DEV: Упростим работу с css (1 часть) 2023-08-16 20:04:36 +03:00
Evg
d220d27225 FIX: Локализация (en) 2023-08-15 06:51:29 +03:00
Evg
d338a77e7e DEV: Мобильная версия (2 часть)
См. https://libarea.ru/post/1507/nachal-peredelyvat-mobilnuyu-versiyu-libarea-i-dr
2023-08-14 16:47:55 +03:00
Evg
86b2f72bdf FIX: Отступ в шапке от строки поиска (RTL) 2023-08-14 15:13:38 +03:00
Evg
5bae5652df DEV: Улучшена локализация
+ при удаление Темы она больше не показывается в Рекомендованных;
+ коррекция css для профиля.
2023-08-12 19:35:58 +03:00
Evg
6e99dc3ef8 DEV: Мобильная версия (css)
См. https://libarea.ru/post/1507/nachal-peredelyvat-mobilnuyu-versiyu-libarea-i-dr
2023-08-10 05:42:19 +03:00
Evg
ef96db9a1b FIX: Локализация (каталог) 2023-08-09 15:12:29 +03:00
Evg
d02a78e0e1 DEV: Незначительные изменения (css) 2023-08-09 12:32:11 +03:00
Evg
e41e022197 UX: Закладки (+ описание сайта) 2023-08-04 07:09:43 +03:00
Evg
6c84d226c8 FIX: Иконка сайта в Закладках (+ поделиться) 2023-08-03 18:42:27 +03:00
Evg
0a992f04cf FIX: RTL 2023-07-29 06:54:46 +03:00
Evg
bd6b8f2081 UX: Локализация 2023-07-27 05:20:06 +03:00
Evg
7898cff395 UX: Удобочитаемый формат числа (темы, профиль) 2023-07-26 07:04:09 +03:00
Evg
8bb8963e78 DEV: RTL CSS 2023-07-23 20:42:28 +03:00
Evg
6b1ebfc2ea FIX: overflow-wrap (css) 2023-07-22 19:29:59 +03:00
Evg
f68460d4bb FIX: Отображение даты инвайтов (админ-панель) 2023-07-21 20:41:52 +03:00
Evg
a4d47659c6 FIX: Конфликт css с prismjs 2023-07-15 16:14:25 +03:00
Evg
190bc07b3e ADD: Свойство word-wrap в комментариях 2023-07-10 21:41:24 +03:00
Evg
3bdbf712c7 DEV: RTL
+ Уберем предупреждение в Parsedown
2023-07-08 05:43:06 +03:00
Evg
0162068f34 FIX: Добавление поста через URL
+ ADD: symfony/css-selector
2023-07-07 06:04:47 +03:00
Evg
7b15bbf979 DEV: URLScraper
+ удалим class Limiter
2023-07-04 21:23:37 +03:00
Evg
3ce6cc3d4b DEV: NSFW (2 часть)
См. https://libarea.ru/post/1451/feature-request-mark-posts-as-nsfw
2023-07-03 06:29:31 +03:00
Evg
387b809375 DEV: NSFW (1 часть) 2023-07-02 08:11:15 +03:00
Evg
58ef5a9ed0 FIX: Добавление поста 2023-06-29 10:12:08 +03:00
Evg
4784f9dbda DEV: Изменения в URLScraper
+ удалим реализацию Hook (далее будет по другому)
2023-06-29 04:03:58 +03:00
Evg
f664130eea FIX: Редактирование связанных (@) категорий 2023-06-28 11:42:38 +03:00
Evg
af62228a38 FIX: RTL Styling 2023-06-25 07:18:48 +03:00
Evg
cb5930c5b6 DELETE: $post и $facet из шапки админ-панели
У нас нет в админ-панели закрепленных заголовков и размещение контента непосредственно в темы / категории.
2023-06-24 07:19:57 +03:00
Evg
e377d82e80 UX: Удалим разделительную полосу в меню участника
См. https://libarea.ru/post/1413/dev-predlozheniya-i-oshibki
2023-06-24 06:11:28 +03:00
Evg
7db7630ccd FIX: GROUP BY (only_full_group_by) 2023-06-23 05:15:23 +03:00
Evg
c45ef3dcbe ADD: История статусов 2023-06-23 03:13:05 +03:00
Evg
7d881a1947 ADD: Manifest 2023-06-22 05:16:30 +03:00
Evg
ad5643f039 UX: Заголовок темы 2023-06-21 15:56:09 +03:00
Evg
c23c20841a ADD: TABLE items_status 2023-06-17 06:10:51 +03:00
Evg
c2e957ba76 DEV: Админ-панель (каталог, 2 часть) 2023-06-16 08:17:18 +03:00
Evg
8b697e6ea9 DEV: Админ-панель (каталог, 2 часть) 2023-06-16 07:08:25 +03:00
Evg
571acfcbe5 DEV: Админ-панель (каталог, 1 часть) 2023-06-15 04:54:31 +03:00
Evg
77892936fd EDIT: Локализация (каталог) 2023-06-14 19:32:37 +03:00
Evg
b490209c25 DEV: Перенесем "Все комментарии" в каталог 2023-06-14 04:46:26 +03:00
Evg
6d2b9f1f38 DEV: Упростим контроллеры (каталог) 2023-06-13 08:32:32 +03:00
Evg
840532c073 FIX: Страница категории 2023-06-13 07:15:03 +03:00
Evg
e1eea844fc UX: Администрирование каталога 2023-06-10 21:29:00 +03:00
Evg
43cb8d4a75 UX: Админ-панель 2023-06-09 05:30:14 +03:00
Evg
ce328c8aba ADD: Метод httpCode() 2023-06-08 06:01:54 +03:00
Evg
52b0ed9518 UX: Локализация 2023-06-07 07:04:13 +03:00
Evg
241b3da099 UX: Меню ответов 2023-06-05 05:43:07 +03:00
Evg
5882c274a7 DEV: Незначительные изменения 2023-06-04 10:11:39 +03:00
Evg
58a9d9c009 FIX: Редактор (шаблон minimum) 2023-06-02 08:06:49 +03:00
Evg
54dfe7b712 DEV: Code highlighting и др. 2023-06-02 02:18:20 +03:00
Evg
49c2dbf7e5 DEV: Изменение поста под администратором 2023-06-02 01:41:13 +03:00
Evg
3650e8f129 EDIT: Метатеги поста 2023-06-01 19:32:22 +03:00
Evg
53f52fa571 DEV: Незначительные изменения 2023-06-01 15:49:53 +03:00
Evg
e21797c750 FIX: Пагинация (админ-панель) 2023-05-28 10:44:24 +03:00
Evg
d4bf393381 FIX: css RTL 2023-05-28 04:38:32 +03:00
Evg
1d90e27b77 DEV: Упрощение добавление фасета (темы, блога...)
См. https://libarea.ru/post/1424/ux-improvement-suggest-and-general-suggestion
2023-05-27 15:29:10 +03:00
Evg
ec25d7abd1 FIX: Рекомендованные сайты 2023-05-26 14:08:50 +03:00
Evg
301b349505 DEV: Удаление варианта опроса 2023-05-24 04:50:35 +03:00
Evg
0dcda1c8d2 FIX: Ссылка на реплики в каталоге 2023-05-23 06:08:47 +03:00
Evg
eacb9fba58 DEV: Незначительные улучшения 2023-05-22 20:35:47 +03:00
Evg
aaacd4adf4 DEV: Использование в каталоге хостов
См. https://libarea.ru/post/1413/dev-predlozheniya-i-oshibki
2023-05-22 06:13:10 +03:00
Evg
41a9e7f60a DEV: Ссылка на Telegram в профиле
См. https://libarea.ru/post/1416/ssylka-na-telegram-v-profile-na-libarea
2023-05-20 20:17:56 +03:00
Evg
c667efc0cb ADD: В логи добавление фасета
См. https://libarea.ru/post/1414/how-to-hide-topic-creator-from-wiki-page
2023-05-19 08:58:55 +03:00
Evg
f1665aca87 FIX: Url сайта в каталоге при поиске
+ см. https://libarea.ru/post/1413/dev-predlozheniya-i-oshibki
2023-05-17 15:19:45 +03:00
Evg
6f9392f588 DEV: Отделим каталог (Route) 2023-05-15 12:15:11 +03:00
Evg
0ca76f8b59 DEV: Проверка дублей сайтов в реальном времени
FIX: Добавление поста по URL
FIX: Локализация
2023-05-14 21:42:00 +03:00
Evg
931d58437e EDIT: Поле comment_comment_id / comment_parent_id 2023-05-14 16:35:41 +03:00
Evg
99bd4ae683 FIX: Добавление сайта 2023-05-14 07:34:26 +03:00
Evg
cda8825f07 DEV: Подразделы сайта 2023-05-13 07:59:54 +03:00
Evg
0a8fae1c6d DEV: Каталог (вынесем js для модуля) 2023-05-12 20:27:38 +03:00
Evg
615fe8b226 EDIT: Подразделы сайта (Каталог) 2023-05-10 05:51:58 +03:00
Evg
466b08b145 DEV: Каталог (редактирование SLUG) 2023-05-09 16:00:46 +03:00
Evg
e441c5c85d DEV: Каталог (+ поле item_slug) ...
+ перенаправление и оптимизация css.
2023-05-09 09:43:06 +03:00
Evg
5026ebf03b DEV: Каталог. Работа с поддоменами.
Определение, группировка и показ.
2023-05-09 06:35:56 +03:00
Evg
dd5bfe0b33 UPDATE: Utopia Domains 2023-05-08 08:40:15 +03:00
Evg
dc05d11ea2 FIX: Прикрепление голосования к сайту 2023-05-05 16:49:42 +03:00
Evg
7c13941a2a DEV: Незначительные изменения (css) 2023-05-04 19:31:10 +03:00
Evg
2f0613c6dc DEV: Вынесем css каталога (для модуля) 2023-05-04 18:35:15 +03:00
Evg
b78ed71285 DEV: setcookie(httponly: true) 2023-05-04 08:12:16 +03:00
Evg
dcb1ec25aa EDIT: Избыточность (по validator.w3.org) 2023-05-02 05:02:26 +03:00
Evg
a1f626282e DEV: For > PHP8.1 2023-05-02 03:13:27 +03:00
Evg
7431992062 DEV: For > PHP8.1 2023-05-02 03:07:42 +03:00
Evg
7800acba57 UX: Админ-панель 2023-05-01 15:44:18 +03:00
Evg
a51807c203 FIX: Невозможно просканировать (PageSpeed Insights) 2023-05-01 08:35:46 +03:00
Evg
c7be44ad20 FIX: Показ удаленных Тем, Блогов в общем списке 2023-05-01 07:05:17 +03:00
Evg
063a7353cf DEV: Незначительные изменения 2023-04-29 16:36:37 +03:00
Evg
b06848edaa ADD: Таблицы Polls* и индексы 2023-04-28 08:07:24 +03:00
Evg
cf287a80b7 DEV: Локализация 2023-04-26 05:12:03 +03:00
Evg
0ad2f75a8a UX: Выделим Опрос (css) 2023-04-25 14:03:09 +03:00
Evg
a9ad2cf49e ADD: Закрытие Опроса 2023-04-25 07:57:44 +03:00
Evg
08ca6e43fb DEV: Breadcrumb (вынесем из каталога) 2023-04-24 14:31:10 +03:00
Evg
750ccee287 FIX: Пересчет Постов в Темах (с учетом удаленных)
+ корректное отображение удаленного комментария (для персонала), если данный комментарий выбран.
+ разная цветовая гамма в progress...
2023-04-23 07:01:37 +03:00
Evg
defedcf978 UX: Голосование 2023-04-22 06:18:16 +03:00
Evg
b26255a47c DEV: Голосование...
См.: https://libarea.ru/post/1384/dev-protestiruem-opros-prikreplennyy-k-postu
2023-04-21 19:20:59 +03:00
Evg
abb92462f1 FIX: Опросы
См. пример: https://libarea.ru/post/1384/dev-protestiruem-opros-prikreplennyy-k-postu
2023-04-21 05:30:14 +03:00
Evg
8ff2eecb4a DEV: Добавим голосование в каталог 2023-04-21 04:54:06 +03:00
Evg
d20a4c9aac DEV: Голосование 2023-04-20 05:18:49 +03:00
Evg
9f9c89b3c4 DEV: Голосование (тестирование) 2023-04-19 04:54:14 +03:00
Evg
118dd1291d DEV: Голосование (тестирование) 2023-04-18 19:44:03 +03:00
Evg
9a2e8d72ae ADD: Голосование (для тестирования) 2023-04-18 06:02:04 +03:00
Evg
b8d8c280d5 DEV: Голосование 2023-04-17 05:33:46 +03:00
Evg
deb51d3ef8 DEV: Локализация (голосование) 2023-04-16 07:21:20 +03:00
Evg
57d462c543 ADD: Локализация (опросы) 2023-04-15 08:03:46 +03:00
Evg
7bdddf4cae DEV: Добавление сайта из Категории 2023-04-11 06:08:19 +03:00
Evg
da58cf3682 FIX: Лента (показ всех постов)
+ добавим обработку (image/webp)
2023-04-05 04:52:38 +03:00
Evg
9cd4faf1a9 FIX: Локализация 2023-04-03 20:12:06 +03:00
Evg
64e7e951a0 ADD: Twitter Cards 2023-04-03 04:47:22 +03:00
Evg
67b42487ea DEV: Показ вкладки "Все" в ленте
Сделаем возможным показать вкладку Все (в ленте) неавторизированным пользователям.

См. https://libarea.ru/post/1093/gorizontalnye-vkladki-v-lente-skript-soobshchestva-libarea#answer_2596
2023-04-02 08:32:32 +03:00
Evg
38eb632727 FIX: Пересчет количество ответов (при удаление)
+ UX удаленных ответов.
2023-04-01 05:32:13 +03:00
Evg
1796c75084 ADD: class PHPMailer
Вопросы с Gmail Google решены...
2023-03-31 03:50:27 +03:00
Evg
482c8483c8 DEV: Незначительные изменения 2023-03-30 06:48:25 +03:00
Evg
88a841256e ADD: class Session 2023-03-29 06:34:50 +03:00
Evg
5e247d3420 DEV: Незначительные изменения 2023-03-29 05:57:59 +03:00
Evg
291aed3a1d FIX: Сдвоенные уведомления 2023-03-27 06:24:57 +03:00
Evg
7cd82480b1 DEV: UX поста и локализация
+ Проверка типов файлов, уберем ошибку при хакинге js.
2023-03-24 12:51:26 +03:00
Evg
463d9c2ad3
Merge pull request #27 from Vilarik/patch-04
Fix background color of resized image
2023-03-24 12:24:04 +03:00
Vilarik
9b4c856b51 Fix background color of resized image 2023-03-24 00:21:57 +03:00
Evg
92a98f6c38 DEV: Удаление профиля (3 часть работ) 2023-03-23 20:24:32 +03:00
Evg
cf586f74b0
Merge pull request #26 from Vilarik/patch-03
Update icons in Post Tile
2023-03-22 19:34:27 +03:00
Vilarik
9eff659d27 Update icons in Post Tile 2023-03-22 18:42:31 +03:00
Evg
97622e40ce DEV: Удаление профиля (2 часть работ) 2023-03-21 16:41:22 +03:00
Evg
cd0ff57e05 DEV: Локализация (для удаление профиля) 2023-03-21 06:22:28 +03:00
Evg
882a7655c5 ADD: CSS for Tagify with noTags but it's required
См. https://github.com/LibArea/libarea/pull/25
2023-03-21 06:12:53 +03:00
Evg
ccb9c30bc2 EDIT: Показ фотографий участника (модель) 2023-03-19 05:19:12 +03:00
Evg
f1441ca3f1 UPDATE: HLEB v1.7.0
+ перенесем Parsedown, Parsedown Extra и Parsedown Extra Plugin. См. https://libarea.ru/post/1330/dev-nekotorye-raboty-i-voyna-s-oshibkami
2023-03-18 06:02:23 +03:00
Evg
0c88ef0049 DEV: Мин. PHP8+
См. https://libarea.ru/post/1321/dev-vozmozhnost-izmenyat-email-nekotorye-plany
2023-03-17 07:07:32 +03:00
Evg
766c17f3c6 DEV: Изменение Email (3 часть) 2023-03-16 11:56:31 +03:00
Evg
2ad4923de9 DEV: Изменение Email (2 часть) 2023-03-15 20:51:21 +03:00
Evg
7f59cb1b4f
Merge pull request #24 from Vilarik/patch-01
Small improvment  'Badge' related code
2023-03-15 20:36:30 +03:00
Vilarik
058f527488 Change 'Remove Badge' action type <span> to <a> 2023-03-15 19:20:21 +03:00
Vilarik
c359ab1c16 Changing wrong of HTML code for 'Tester' badget 2023-03-15 19:16:52 +03:00
Evg
1a9fa3dbb4 DEV: Изменение Email (1 часть)
См. https://libarea.ru/post/1321/dev-vozmozhnost-izmenyat-email-nekotorye-plany
2023-03-15 06:01:34 +03:00
Evg
2f260a4c89 DEV: Незначительные изменения 2023-03-14 05:25:50 +03:00
Evg
5363ccdcef UX: Постинг поста в Тему или Блог
Если мы находимся непосредственно в Теме или созданном Блоге.
2023-03-13 05:53:40 +03:00
400 changed files with 11879 additions and 5627 deletions

View file

@ -49,7 +49,7 @@ Further:
* Log in to your account using administrator credentials: `ss@sdf.ru` / `qwer14qwer14`
* Or user: `test@test.ru` / `test@test.ru`
PHP 7.4+, MySQL 8+ or > MariaDB 10.2.2
PHP 8+, MySQL 8+ or > MariaDB 10.2.2
Fully assembled releases can be downloaded at the office. support site: https://libarea.com/

View file

@ -15,7 +15,7 @@ class ActionController extends Controller
$content_id = Request::getPostInt('content_id');
$type = Request::getPost('type');
$allowed = ['post', 'comment', 'answer', 'reply', 'item'];
$allowed = ['post', 'comment', 'reply', 'item'];
if (!in_array($type, $allowed)) {
return false;
}
@ -23,6 +23,7 @@ class ActionController extends Controller
// Access check
// Проверка доступа
$info_type = ActionModel::getInfoTypeContent($content_id, $type);
if (Access::author($type, $info_type) == false) {
redirect('/');
}
@ -37,11 +38,6 @@ class ActionController extends Controller
$url = post_slug($info_type['comment_post_id'], $post['post_slug']) . '#comment_' . $info_type['comment_id'];
$action_type = 'comment';
break;
case 'answer':
$post = PostModel::getPost($info_type['answer_post_id'], 'id', $this->user);
$url = post_slug($info_type['answer_post_id'], $post['post_slug']) . '#answer_' . $info_type['answer_id'];
$action_type = 'answer';
break;
case 'reply':
$url = '/';
$action_type = 'reply';

View file

@ -1,97 +0,0 @@
<?php
namespace App\Controllers\Answer;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\PostPresence;
use App\Models\{NotificationModel, ActionModel, AnswerModel, PostModel};
use App\Validate\Validator;
use UserData;
class AddAnswerController extends Controller
{
public function create()
{
$post = PostPresence::index(Request::getPostInt('post_id'), 'id');
$url_post = post_slug($post['post_id'], $post['post_slug']);
Validator::Length($content = $_POST['content'], 6, 5000, 'content', $url_post);
// Let's check the stop words, url
// Проверим стоп слова и url
$trigger = (new \App\Services\Audit())->prohibitedContent($content);
$this->union($post, $url_post, $content);
$last_id = AnswerModel::add($post['post_id'], $content, $trigger);
// Add an audit entry and an alert to the admin
// Аудит и оповещение персоналу
if ($trigger === false) {
(new \App\Services\Audit())->create('answer', $last_id, url('admin.audits'));
}
$url = $url_post . '#answer_' . $last_id;
$this->notif($content, $post, $url);
ActionModel::addLogs(
[
'id_content' => $last_id,
'action_type' => 'answer',
'action_name' => 'added',
'url_content' => $url,
]
);
redirect($url);
}
public function union($post, $url_post, $content)
{
if (config('publication.merge_answer_post') == false) {
return true;
}
// Staff can write a response under their post
// Персонал может писать ответ под своим постом
if (UserData::checkAdmin()) {
return true;
}
// If there are no replies to the post and the author of the post = the author of the answer, then add the answer to the end of the post
// Если ответов на пост нет и автор поста = автора ответа, то дописываем ответ в конец поста
if ((AnswerModel::getNumberAnswers($post['post_id']) == null) && ($post['post_user_id'] == $this->user['id'])) {
AnswerModel::mergePost($post['post_id'], $content);
redirect($url_post);
}
return true;
}
// Notifications when adding a answer
// Уведомления при добавлении ответа
public function notif($content, $post, $url)
{
// Contact via @
// Обращение через @
if ($message = \App\Services\Parser\Content::parseUsers($content, true, true)) {
(new \App\Controllers\NotificationController())->mention(NotificationModel::TYPE_ADDRESSED_ANSWER, $message, $url, $post['post_user_id']);
}
// Who is following this question/post
// Кто подписан на данный вопрос / пост
if ($focus_all = PostModel::getFocusUsersPost($post['post_id'])) {
foreach ($focus_all as $focus_user) {
if ($focus_user['signed_user_id'] != $this->user['id']) {
NotificationModel::send($focus_user['signed_user_id'], NotificationModel::TYPE_AMSWER_POST, $url);
}
}
}
}
}

View file

@ -1,74 +0,0 @@
<?php
namespace App\Controllers\Answer;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\PostPresence;
use App\Services\Сheck\AnswerPresence;
use App\Models\AnswerModel;
use App\Models\User\UserModel;
use App\Validate\Validator;
use Meta, Access;
use App\Traits\Author;
class EditAnswerController extends Controller
{
use Author;
// Edit form answer
public function index()
{
$answer = AnswerPresence::index(Request::getInt('id'));
if (Access::author('answer', $answer) == false) {
return false;
}
$post = PostPresence::index($answer['answer_post_id'], 'id');
return $this->render(
'/answer/edit',
[
'meta' => Meta::get(__('app.edit_answer')),
'data' => [
'post' => $post,
'answer' => $answer,
'user' => UserModel::getUser($answer['answer_user_id'], 'id'),
'sheet' => 'edit-answers',
'type' => 'answer',
]
]
);
}
public function change()
{
$answer_id = Request::getPostInt('answer_id');
$content = $_POST['content']; // для Markdown
// Access check
$answer = AnswerModel::getAnswerId($answer_id);
if (Access::author('answer', $answer) == false) {
return false;
}
$post = PostPresence::index($answer['answer_post_id'], 'id');
$url_post = post_slug($answer['answer_post_id'], $post['post_slug']);
Validator::Length($content, 6, 5000, 'content', url('content.edit', ['type' => 'answer', 'id' => $answer['answer_id']]));
AnswerModel::edit(
[
'answer_id' => $answer['answer_id'],
'answer_content' => $content,
'answer_user_id' => $this->selectAuthor($answer['answer_user_id'], Request::getPost('user_id')),
'answer_modified' => date("Y-m-d H:i:s"),
]
);
is_return(__('msg.change_saved'), 'success', $url_post . '#answer_' . $answer['answer_id']);
}
}

View file

@ -3,16 +3,12 @@
namespace App\Controllers\Auth;
use App\Controllers\Controller;
use Session;
class LogoutController extends Controller
{
public function index()
{
if (!isset($_SESSION)) {
session_start();
}
session_destroy();
setcookie("remember", "", time() - 3600, "/");
redirect('/');
Session::logout();
}
}

View file

@ -86,7 +86,7 @@ class RememberController extends MainController
]
);
setcookie("remember", $token, $expires, '/');
setcookie("remember", $token, $expires, '/', httponly: true);
}
// Запомнить меня
@ -116,6 +116,6 @@ class RememberController extends MainController
// Установим токен
$token = $selector . ':' . $validator;
setcookie("remember", $token, $expires, '/');
setcookie("remember", $token, $expires, '/', httponly: true);
}
}

View file

@ -4,6 +4,7 @@ namespace App\Controllers\Auth;
use Hleb\Scheme\App\Controllers\MainController;
use App\Models\AuthModel;
use Session;
class SessionController extends MainController
{
@ -16,11 +17,7 @@ class SessionController extends MainController
public static function annul($user_id)
{
if (!isset($_SESSION)) {
session_start();
}
session_destroy();
Session::logout();
AuthModel::deleteTokenByUserId($user_id);

View file

@ -4,47 +4,43 @@ namespace App\Controllers\Comment;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\PostPresence;
use App\Services\Сheck\AnswerPresence;
use App\Models\{NotificationModel, ActionModel, AnswerModel, CommentModel};
use App\Services\DetectMobile;
use App\Services\Сheck\{PostPresence, CommentPresence};
use App\Models\{NotificationModel, ActionModel, CommentModel, PostModel};
use App\Validate\Validator;
use UserData;
class AddCommentController extends Controller
{
// Show the form for adding a comment
// Show the form for adding a комментария
// Покажем форму добавление комментария
public function index()
{
insert(
'/_block/form/add-form-comment',
[
'data' => [
'answer_id' => Request::getPostInt('answer_id'),
'comment_id' => Request::getPostInt('comment_id'),
],
]
);
insert('/_block/form/add-comment');
}
// Adding a comment
public function create()
{
$answer_id = Request::getPostInt('answer_id'); // на какой ответ
$comment_id = Request::getPostInt('comment_id'); // на какой комментарий
$answer = AnswerPresence::index($answer_id);
$post = PostPresence::index($answer['answer_post_id'], 'id');
{
if ($post_id = Request::getPostInt('post_id')) {
$post = PostPresence::index($post_id, 'id');
}
if ($comment_id = Request::getPostInt('comment_id')) {
$comment = CommentPresence::index($comment_id);
$post = PostPresence::index($comment['comment_post_id'], 'id');
}
$url_post = post_slug($post['post_id'], $post['post_slug']);
Validator::Length($content = $_POST['comment'], 6, 2024, 'content', $url_post);
Validator::Length($content = $_POST['content'], 6, 5000, 'content', $url_post);
// Let's check the stop words, url
// Проверим стоп слова, url
// Проверим стоп слова и url
$trigger = (new \App\Services\Audit())->prohibitedContent($content);
$last_id = CommentModel::add($post['post_id'], $answer_id, $comment_id, $content, $trigger);
$this->union($post, $url_post, $content);
$last_id = CommentModel::add($post['post_id'], $comment_id, $content, $trigger, DetectMobile::index());
// Add an audit entry and an alert to the admin
// Аудит и оповещение персоналу
@ -54,13 +50,13 @@ class AddCommentController extends Controller
$url = $url_post . '#comment_' . $last_id;
$this->notif($answer_id, $comment_id, $content, $url);
$this->notifPost($content, $post, $comment_id, $url);
ActionModel::addLogs(
[
'id_content' => $last_id,
'action_type' => 'comment',
'action_name' => 'added',
'action_name' => 'comment',
'url_content' => $url,
]
);
@ -68,28 +64,57 @@ class AddCommentController extends Controller
redirect($url);
}
// Notifications when adding a comment
// Уведомления при добавлении комментария
public function notif($answer_id, $comment_id, $content, $url)
public function union($post, $url_post, $content)
{
// Notification to the author of the answer that there is a comment (do not write to ourselves)
// Оповещение автору ответа, что есть комментарий (себе не записываем)
$answ = AnswerModel::getAnswerId($answer_id);
if ($this->user['id'] != $answ['answer_user_id']) {
NotificationModel::send($answ['answer_user_id'], NotificationModel::TYPE_COMMENT_ANSWER, $url);
if (config('publication.merge_answer_post') == false) {
return true;
}
if ($comment_id) {
$comment = CommentModel::getCommentsId($comment_id);
if ($this->user['id'] != $comment['comment_user_id']) {
NotificationModel::send($comment['comment_user_id'], NotificationModel::TYPE_COMMENT_COMMENT, $url);
}
// Staff can write a response under their post
// Персонал может писать ответ под своим постом
if (UserData::checkAdmin()) {
return true;
}
// If there are no replies to the post and the author of the post = the author of the comment, then add the comment to the end of the post
// Если ответов на пост нет и автор поста = автора ответа, то дописываем ответ в конец поста
if ((CommentModel::getNumberComment($post['post_id']) == null) && ($post['post_user_id'] == $this->user['id'])) {
CommentModel::mergePost($post['post_id'], $content);
redirect($url_post);
}
return true;
}
// Notifications when adding a answer
// Уведомления при добавлении ответа
public function notifPost($content, $post, $comment_id, $url)
{
// Contact via @
// Обращение через @
if ($message = \App\Services\Parser\Content::parseUsers($content, true, true)) {
(new \App\Controllers\NotificationController())->mention(NotificationModel::TYPE_ADDRESSED_COMMENT, $message, $url, $comment['comment_user_id']);
(new \App\Controllers\NotificationController())->mention(NotificationModel::TYPE_ADDRESSED_ANSWER, $message, $url, $post['post_user_id']);
}
// Who is following this question/post
// Кто подписан на данный вопрос / пост
if ($focus_all = PostModel::getFocusUsersPost($post['post_id'])) {
foreach ($focus_all as $focus_user) {
if ($focus_user['signed_user_id'] != $this->user['id']) {
NotificationModel::send($focus_user['signed_user_id'], NotificationModel::TYPE_AMSWER_POST, $url);
}
}
}
// Notifications when adding a comment
// Уведомления при добавлении комментария
if ($comment_id) {
$comment = CommentModel::getCommentId($comment_id);
if ($this->user['id'] != $comment['comment_user_id']) {
NotificationModel::send($comment['comment_user_id'], NotificationModel::TYPE_COMMENT_COMMENT, $url);
}
}
}
}

View file

@ -3,35 +3,27 @@
namespace App\Controllers\Comment;
use App\Controllers\Controller;
use App\Models\{CommentModel, AnswerModel};
use App\Models\CommentModel;
use Meta, Html;
class CommentController extends Controller
{
protected $limit = 10;
// All comments (combining answers and comments for UX)
// Все комментарии (объединение ответов и комментариев для UX)
// All comments
// Все комменатрии
public function index($sheet)
{
$pagesCount = CommentModel::getCommentsCount($this->user, $sheet);
$comments = CommentModel::getComments($this->pageNumber, $this->limit, $this->user, $sheet);
$pagesCount = AnswerModel::getAnswersCount($sheet);
$answers = AnswerModel::getAnswers($this->pageNumber, $this->limit, $this->user, $sheet);
$pagesCount = CommentModel::getCommentsCount($sheet);
$comments = CommentModel::getComments($this->pageNumber, $sheet);
$m = [
'og' => false,
'url' => url('comments'),
];
$mergedArr = array_merge($comments, $answers);
usort($mergedArr, function ($a, $b) {
return ($b['comment_date'] ?? $b['answer_date']) <=> ($a['comment_date'] ?? $a['answer_date']);
});
return $this->render(
'/comment/comments',
'/comments/all',
[
'meta' => Meta::get(__('meta.all_comments'), __('meta.comments_desc'), $m),
'data' => [
@ -39,23 +31,10 @@ class CommentController extends Controller
'pNum' => $this->pageNumber,
'sheet' => $sheet,
'type' => 'comments',
'comments' => $mergedArr,
'comments' => $comments,
]
]
);
}
public function lastComment()
{
$comments = CommentModel::getComments(1, 5, $this->user, 'all');
$result = [];
foreach ($comments as $ind => $row) {
$row['content'] = fragment($row['comment_content'], 98);
$row['date'] = Html::langDate($row['comment_date']);
$result[$ind] = $row;
}
return json_encode($result, JSON_PRETTY_PRINT);
}
}

View file

@ -4,59 +4,71 @@ namespace App\Controllers\Comment;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\{PostPresence, CommentPresence};
use App\Services\Сheck\PostPresence;
use App\Services\Сheck\CommentPresence;
use App\Models\CommentModel;
use App\Models\User\UserModel;
use App\Validate\Validator;
use Access;
use Meta, Access;
use App\Traits\Author;
class EditCommentController extends Controller
{
// Comment Editing Form
// Форма редактирования комментария
use Author;
// Edit form comment
public function index()
{
// Access verification
// Проверка доступа
$comment = CommentPresence::index(Request::getPostInt('comment_id'));
$comment = CommentPresence::index(Request::getInt('id'));
if (Access::author('comment', $comment) == false) {
return false;
}
insert(
'/_block/form/edit-form-comment',
$post = PostPresence::index($comment['comment_post_id'], 'id');
return $this->render(
'/comments/edit',
[
'meta' => Meta::get(__('app.edit_comment')),
'data' => [
'comment_id' => $comment['comment_id'],
'comment_content' => $comment['comment_content'],
],
'user' => $this->user
'post' => $post,
'comment' => $comment,
'user' => UserModel::getUser($comment['comment_user_id'], 'id'),
'sheet' => 'edit-answers',
'type' => 'comment',
]
]
);
}
public function change()
{
// Access verification
$comment = CommentPresence::index(Request::getPostInt('comment_id'));
$comment_id = Request::getPostInt('comment_id');
$content = $_POST['content']; // для Markdown
// Access check
$comment = CommentModel::getCommentId($comment_id);
if (Access::author('comment', $comment) == false) {
redirect('/');
return false;
}
$post = PostPresence::index($comment['comment_post_id'], 'id');
$redirect = post_slug($post['post_id'], $post['post_slug']) . '#comment_' . $comment['comment_id'];
$url_post = post_slug($comment['comment_post_id'], $post['post_slug']);
$content = $_POST['comment']; // для Markdown
Validator::length($content, 3, 5500, 'content', $redirect);
Validator::Length($content, 6, 5000, 'content', url('content.edit', ['type' => 'comment', 'id' => $comment['comment_id']]));
CommentModel::edit(
[
'comment_id' => $comment['comment_id'],
'comment_content' => $content,
'comment_modified' => date("Y-m-d H:i:s"),
'comment_id' => $comment['comment_id'],
'comment_content' => $content,
'comment_user_id' => $this->selectAuthor($comment['comment_user_id'], Request::getPost('user_id')),
'comment_modified' => date("Y-m-d H:i:s"),
]
);
redirect($redirect);
is_return(__('msg.change_saved'), 'success', $url_post . '#comment_' . $comment['comment_id']);
}
}

View file

@ -27,7 +27,7 @@ class Controller extends MainController
return $pageNumber <= 1 ? 1 : $pageNumber;
}
public static function render(string $name, array $data = [], $component = false)
public static function render(string $name, array $data = [], string $part = 'base')
{
self::closing();
@ -36,21 +36,19 @@ class Controller extends MainController
$body = 'default';
}
$file = ($component == false) ? 'base' : $component;
if (!file_exists(TEMPLATES . DIRECTORY_SEPARATOR . $header . '/global/' . $file . '-header.php')) {
if (!file_exists(TEMPLATES . DIRECTORY_SEPARATOR . $header . '/global/' . $part . '-header.php')) {
$header = 'default';
}
if (!file_exists(TEMPLATES . DIRECTORY_SEPARATOR . $footer . '/global/' . $file . '-footer.php')) {
if (!file_exists(TEMPLATES . DIRECTORY_SEPARATOR . $footer . '/global/' . $part . '-footer.php')) {
$footer = 'default';
}
return render(
[
$header . '/global/' . $file . '-header',
$header . '/global/' . $part . '-header',
$body . '/content' . $name,
$footer . '/global/' . $file . '-footer'
$footer . '/global/' . $part . '-footer'
],
$data
);

View file

@ -4,7 +4,7 @@ namespace App\Controllers\Facets;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Models\{FacetModel, SubscriptionModel};
use App\Models\{FacetModel, SubscriptionModel, ActionModel};
use Meta;
use App\Validate\RulesFacet;
@ -37,11 +37,11 @@ class AddFacetController extends Controller
$new_facet_id = FacetModel::add(
[
'facet_title' => $data['facet_title'],
'facet_description' => $data['facet_description'],
'facet_description' => __('app.meta_description'),
'facet_short_description' => $data['facet_short_description'],
'facet_slug' => strtolower($data['facet_slug']),
'facet_img' => 'facet-default.png',
'facet_seo_title' => $data['facet_seo_title'],
'facet_seo_title' => $data['facet_short_description'],
'facet_user_id' => $this->user['id'],
'facet_type' => $type,
]
@ -51,6 +51,17 @@ class AddFacetController extends Controller
$msg = $type == 'blog' ? __('msg.blog_added') : __('msg.change_saved');
is_return($msg, 'success', url('redirect.facet', ['id' => $new_facet_id['facet_id']]));
$url = url('redirect.facet', ['id' => $new_facet_id['facet_id']]);
ActionModel::addLogs(
[
'id_content' => $new_facet_id['facet_id'],
'action_type' => $type,
'action_name' => 'added',
'url_content' => $url,
]
);
is_return($msg, 'success', $url);
}
}

View file

@ -48,11 +48,7 @@ class BlogFacetController extends Controller
'facet_signed' => SubscriptionModel::getFocus($facet['facet_id'], 'facet'),
'info' => markdown($facet['facet_info'] ?? false, 'text'),
],
'facet' => [
'facet_id' => $facet['facet_id'],
'facet_type' => $facet['facet_type'],
'facet_user_id' => $facet['facet_user_id']
],
'facet' => ['facet_id' => $facet['facet_id'], 'facet_type' => $facet['facet_type'], 'facet_user_id' => $facet['facet_user_id']],
]
);
}

View file

@ -62,7 +62,9 @@ class EditFacetController extends Controller
$facet_user_id = $this->selectAuthor($facet['facet_user_id'], Request::getPost('user_id'));
$post_related = $this->relatedPost();
$facet_top_level = $data['facet_top_level'] ?? false;
$facet_is_comments = $data['facet_is_comments'] ?? false;
FacetModel::edit(
[
@ -77,6 +79,7 @@ class EditFacetController extends Controller
'facet_top_level' => $facet_top_level == 'on' ? 1 : 0,
'facet_post_related' => $post_related,
'facet_type' => $new_type,
'facet_is_comments' => $facet_is_comments == 'on' ? 1 : 0,
]
);

View file

@ -6,7 +6,6 @@ use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\FacetPresence;
use App\Services\Meta\Facet;
use App\Models\User\UserModel;
use App\Models\{FeedModel, SubscriptionModel, FacetModel, PostModel};
class TopicFacetController extends Controller
@ -98,7 +97,6 @@ class TopicFacetController extends Controller
'writers' => FacetModel::getWriters($facet['facet_id'], 15),
'low_topics' => FacetModel::getLowLevelList($facet['facet_id']),
'low_matching' => FacetModel::getLowMatching($facet['facet_id']),
'user' => UserModel::getUser($facet['facet_user_id'], 'id'),
];
}
}

View file

@ -23,6 +23,10 @@ class FormController extends Controller
return (new Post\AddPostController)->index($this->type);
}
if (in_array($this->type, ['poll'])) {
return (new Poll\AddPollController)->index($this->type);
}
if (in_array($this->type, config('facets.permitted'))) {
return (new Facets\AddFacetController)->index($this->type);
}
@ -47,8 +51,12 @@ class FormController extends Controller
return (new Facets\EditFacetController)->index($this->type);
}
if ($this->type === 'answer') {
return (new Answer\EditAnswerController)->index();
if ($this->type === 'poll') {
return (new Poll\EditPollController)->index();
}
if ($this->type === 'comment') {
return (new Comment\EditCommentController)->index();
}
if ($this->type === 'item') {
@ -67,12 +75,12 @@ class FormController extends Controller
return (new Post\AddPostController)->create($this->type);
}
if (in_array($this->type, ['topic', 'blog', 'category', 'section'])) {
return (new Facets\AddFacetController)->create($this->type);
if ($this->type === 'poll') {
return (new Poll\AddPollController)->create();
}
if ($this->type === 'answer') {
return (new Answer\AddAnswerController)->create();
if (in_array($this->type, ['topic', 'blog', 'category', 'section'])) {
return (new Facets\AddFacetController)->create($this->type);
}
if ($this->type === 'comment') {
@ -115,8 +123,8 @@ class FormController extends Controller
return (new Facets\EditFacetController)->change($this->type);
}
if ($this->type === 'answer') {
return (new Answer\EditAnswerController)->change();
if ($this->type === 'poll') {
return (new Poll\EditPollController)->change();
}
if ($this->type === 'comment') {

View file

@ -8,16 +8,8 @@ use App\Models\HomeModel;
class HomeController extends Controller
{
protected $limit = 15;
public function index($sheet)
{
$latest_answers = HomeModel::latestAnswers();
$topics_user = HomeModel::subscription();
$pagesCount = HomeModel::feedCount($topics_user, $sheet);
$posts = HomeModel::feed($this->pageNumber, $this->limit, $topics_user, $sheet);
$items = HomeModel::latestItems(3); // (LIMIT)
// Topics signed by the participant. If a guest, then default.
// Темы на которые подписан участник. Если гость, то дефолтные.
$topics = \App\Models\FacetModel::advice();
@ -27,15 +19,15 @@ class HomeController extends Controller
[
'meta' => Home::metadata($sheet),
'data' => [
'pagesCount' => ceil($pagesCount / $this->limit),
'pagesCount' => HomeModel::feedCount($sheet),
'pNum' => $this->pageNumber,
'sheet' => $sheet,
'type' => 'main',
'latest_answers' => $latest_answers,
'topics_user' => $topics_user,
'posts' => $posts,
'topics' => $topics,
'items' => $items,
'type' => 'main',
'latest_comments' => HomeModel::latestComments(),
'topics_user' => HomeModel::subscription(),
'posts' => HomeModel::feed($this->pageNumber, $sheet),
'items' => HomeModel::latestItems(),
],
],
);
@ -45,10 +37,9 @@ class HomeController extends Controller
// Бесконечный скролл
public function scroll()
{
$type = Request::get('type') == 'all' ? 'all' : 'main.feed';
$type = Request::get('type') == 'all' ? 'all' : 'main.feed';
$topics_user = HomeModel::subscription();
$posts = HomeModel::feed($this->pageNumber, $this->limit, $topics_user, $type);
$posts = HomeModel::feed($this->pageNumber, $type);
$this->insert(
'/content/post/type-post',
@ -56,7 +47,7 @@ class HomeController extends Controller
'data' => [
'pages' => $this->pageNumber,
'sheet' => 'main.feed',
'posts' => $posts,
'posts' => $posts, // $posts = empty($posts) ? 'null' : $posts;
]
]

View file

@ -4,14 +4,20 @@ namespace App\Controllers\Item;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\FacetPresence;
use App\Models\Item\{WebModel, UserAreaModel};
use App\Models\{SubscriptionModel, ActionModel, FacetModel, NotificationModel};
use UserData, Meta, Access;
use App\Validate\RulesItem;
use App\Traits\Slug;
use App\Traits\Poll;
class AddItemController extends Controller
{
use Slug;
use Poll;
// Add Domain Form
// Форма добавление домена
public function index()
@ -20,7 +26,15 @@ class AddItemController extends Controller
redirect('/web');
}
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount($this->user['id']);
// Adding from page topic / blog
// Добавление со странице категории
if ($category_id = Request::getInt('category_id')) {
$category = FacetPresence::index($category_id, 'id', 'category');
}
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount();
Request::getResources()->addBottomScript('/assets/js/catalog.js');
return $this->render(
'/item/add',
@ -28,8 +42,9 @@ class AddItemController extends Controller
'meta' => Meta::get(__('web.add_website')),
'user' => $this->user,
'data' => [
'sheet' => 'add',
'type' => 'web',
'sheet' => 'add',
'type' => 'web',
'category' => $category ?? false,
'user_count_site' => $count_site,
]
],
@ -49,15 +64,21 @@ class AddItemController extends Controller
$published = Request::getPost('published') == 'on' ? 1 : 0;
$published = UserData::checkAdmin() ? $published : 0;
if (WebModel::getSlug($slug = $this->getSlug($data['title']))) {
$slug = $slug . "-";
}
$item_last = WebModel::add(
[
'item_url' => $data['url'],
'item_domain' => $basic_host,
'item_title' => $data['title'],
'item_content' => $data['content'] ?? __('web.desc_formed'),
'item_slug' => $slug,
'item_published' => $published,
'item_user_id' => $this->user['id'],
'item_close_replies' => Request::getPost('close_replies') == 'on' ? 1 : null,
'item_poll' => $this->selectPoll(Request::getPost('poll_id')),
]
);
@ -101,4 +122,12 @@ class AddItemController extends Controller
return true;
}
public function searchUrl()
{
$host = host(Request::getPost('url'));
$result = WebModel::getHost($host);
return json_encode($result, JSON_PRETTY_PRINT);
}
}

View file

@ -0,0 +1,103 @@
<?php
namespace App\Controllers\Item;
use App\Controllers\Controller;
use Hleb\Constructor\Handlers\Request;
use App\Models\Item\{WebModel, UserAreaModel};
use Meta, Msg;
class AdminController extends Controller
{
protected $limit = 15;
protected $user_count = 0;
public function audits()
{
return $this->render(
'/item/admin/audits',
[
'meta' => Meta::get(__('web.audits')),
'data' => [
'sheet' => 'audits',
'items' => WebModel::feedItem(false, false, $this->pageNumber, 'audits', false),
'user_count_site' => $this->user_count,
'audit_count' => UserAreaModel::auditCount(),
]
],
'item',
);
}
public function deleted()
{
return $this->render(
'/item/admin/deleted',
[
'meta' => Meta::get(__('web.deleted')),
'data' => ['items' => WebModel::feedItem(false, false, 'deleted', false)]
],
'item',
);
}
public function comments()
{
return $this->render(
'/item/admin/comments',
[
'meta' => Meta::get(__('web.comments')),
'data' => ['comments' => WebModel::getComments(20)]
],
'item',
);
}
public function status()
{
Request::getResources()->addBottomScript('/assets/js/catalog.js');
$code = Request::get('code');
$pagesCount = 0; // TODO
return $this->render(
'/item/admin/status',
[
'meta' => Meta::get(__('web.status')),
'data' => [
'pagesCount' => ceil($pagesCount / $this->limit),
'pNum' => $this->pageNumber,
'status' => WebModel::getStatus($this->pageNumber, $code),
'code' => $code
]
],
'item',
);
}
public static function httpCode($url)
{
stream_context_set_default([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
],
]);
$headers = get_headers($url);
return (empty($headers[0])) ? 404 : substr($headers[0], 9, 3);
}
// Once a month
public static function updateStatus()
{
$items = WebModel::getForStatus();
foreach ($items as $row) {
WebModel::statusUpdate($row['item_id'], self::httpCode($row['item_url']));
}
Msg::add(__('admin.completed'), 'success');
}
}

View file

@ -4,15 +4,21 @@ namespace App\Controllers\Item;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\ItemPresence;
use App\Services\Tree\BuildTree;
use App\Models\Item\{WebModel, ReplyModel, UserAreaModel};
use App\Models\{PostModel, SubscriptionModel};
use Meta, UserData, Img;
use App\Traits\LastDataModified;
use App\Traits\Poll;
use App\Validate\RulesItem;
class DetailedController extends Controller
{
use LastDataModified;
use Poll;
protected $limit = 25;
@ -20,25 +26,30 @@ class DetailedController extends Controller
// Детальная страница сайта
public function index()
{
$slug = Request::get('slug');
$slug = Request::get('slug');
$id = Request::getInt('id');
$item = WebModel::getItemOne($slug, $this->user['id']);
notEmptyOrView404($item);
$item = self::presence($id, $slug);
if ($item['item_published'] == 0) {
notEmptyOrView404([]);
}
$content_img = Img::PATH['thumbs'] . 'default.png';
if (file_exists(HLEB_PUBLIC_DIR . Img::PATH['thumbs'] . $item['item_domain'] . '.png')) {
$content_img = Img::PATH['thumbs'] . $item['item_domain'] . '.png';
$host = host($item['item_url']);
Request::getResources()->addBottomScript('/assets/js/dialog/dialog.js');
if (file_exists(HLEB_PUBLIC_DIR . Img::PATH['thumbs'] . $host . '.png')) {
$content_img = Img::PATH['thumbs'] . $host . '.png';
}
$m = [
'og' => true,
'imgurl' => $content_img,
'url' => url('website', ['slug' => $item['item_domain']]),
'url' => url('website', ['id' => $item['item_id'], 'slug' => $item['item_slug']]),
];
$title = __('web.website') . ': ' . $item['item_title'];
$description = $item['item_title'] . '. ' . $item['item_content'];
@ -47,21 +58,18 @@ class DetailedController extends Controller
}
$flat = ReplyModel::get($item['item_id'], $this->user);
$tree = !empty($flat) ? self::buildTree(0, $flat) : false;
$tree = !empty($flat) ? BuildTree::index(0, $flat, 'reply') : false;
// Featured Content
// Рекомендованный контент
$facets = WebModel::getItemTopic($item['item_id']);
$similar = WebModel::itemSimilars($item['item_id'], $facets[0]['id'] ?? false, 3);
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount($this->user['id']);
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount();
// Отправка Last-Modified и обработка HTTP_IF_MODIFIED_SINCE
$this->getDataModified($item['item_modified']);
Request::getResources()->addBottomScript('/assets/js/share/goodshare.min.js');
Request::getResources()->addBottomScript('/assets/js/dialog/dialog.js');
return $this->render(
'/item/website',
[
@ -74,31 +82,26 @@ class DetailedController extends Controller
'similar' => $similar ?? [],
'user_count_site' => $count_site,
'related_posts' => $related_posts ?? [],
'poll' => $this->getPoll($item['item_poll']),
'subsections' => RulesItem::getDomains($item['item_domain']),
]
],
'item',
);
}
// https://stackoverflow.com/questions/4196157/create-array-tree-from-array-list/4196879#4196879
public static function buildTree($group, array $flatList)
public static function presence($id, $slug)
{
$grouped = [];
foreach ($flatList as $node) {
$grouped[$node['reply_parent_id']][] = $node;
// Check id and get content data
// Проверим id и получим данные контента
$content = ItemPresence::index($id, 'id');
// If the site slug is different from the data in the database
// Если slug сайта отличается от данных в базе
if ($slug != $content['item_slug']) {
redirect(url('website', ['id' => $content['item_id'], 'slug' => $content['item_slug']]));
}
$fnBuilder = function ($siblings) use (&$fnBuilder, $grouped) {
foreach ($siblings as $k => $sibling) {
$id = $sibling['reply_id'];
if (isset($grouped[$id])) {
$sibling['children'] = $fnBuilder($grouped[$id]);
}
$siblings[$k] = $sibling;
}
return $siblings;
};
return $fnBuilder($grouped[$group]);
return $content;
}
}

View file

@ -9,8 +9,12 @@ use App\Models\PostModel;
use App\Models\Item\{WebModel, UserAreaModel, FacetModel};
use UserData, Meta;
use App\Traits\Breadcrumb;
class DirController extends Controller
{
use Breadcrumb;
protected $limit = 25;
// List of sites by topic (sites by "category")
@ -19,7 +23,7 @@ class DirController extends Controller
{
$grouping = Request::get('grouping');
$sort = Request::get('sort');
self::filter($grouping, $sort);
$category = FacetModel::get(Request::get('slug'), 'slug', $this->user['trust_level']);
@ -31,8 +35,8 @@ class DirController extends Controller
if ($category['facet_post_related']) {
$related_posts = PostModel::postRelated($category['facet_post_related']);
}
$items = WebModel::feedItem($this->pageNumber, $this->limit, $childrens, $this->user, $category['facet_id'], $sort, $grouping);
$items = WebModel::feedItem($childrens, $category['facet_id'], $this->pageNumber, $sort, $grouping);
$pagesCount = WebModel::feedItemCount($childrens, $category['facet_id'], $sort, $grouping);
$m = [
@ -44,9 +48,7 @@ class DirController extends Controller
$description_info = $category['facet_title'] . '. ' . $category['facet_description'];
$description = __('web.' . $sort . '_desc', ['description_info' => $description_info]);
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount($this->user['id']);
$tree = FacetModel::breadcrumb($category['facet_id']);
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount();
return $this->render(
'/item/sites',
@ -62,7 +64,7 @@ class DirController extends Controller
'category' => $category,
'childrens' => $childrens,
'user_count_site' => $count_site,
'breadcrumb' => self::breadcrumb($tree, $sort),
'breadcrumb' => $this->getBreadcrumb($category['facet_id'], $sort),
'characteristics' => WebModel::getTypesWidget($category['facet_id']),
'low_matching' => FacetModel::getLowMatching($category['facet_id']),
]
@ -89,21 +91,6 @@ class DirController extends Controller
}
}
// Bread crumbs
public static function breadcrumb($tree, $sort)
{
$arr = [
['name' => __('web.catalog'), 'link' => url('web')]
];
$result = [];
foreach ($tree as $row) {
$result[] = ["name" => $row['name'], "link" => url('category', ['sort' => $sort, 'slug' => $row['link']])];
}
return array_merge($arr, $result);
}
// Click-throughs
// Переходы
public function cleek()

View file

@ -6,10 +6,12 @@ use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\ItemPresence;
use App\Models\Item\WebModel;
use App\Models\{FacetModel, PostModel, NotificationModel};
use App\Models\{FacetModel, PostModel, NotificationModel, PollModel};
use App\Models\User\UserModel;
use UserData, Meta, Access;
use App\Traits\Poll;
use App\Traits\Slug;
use App\Traits\Author;
use App\Traits\Related;
@ -17,13 +19,15 @@ use App\Validate\RulesItem;
class EditItemController extends Controller
{
use Poll;
use Slug;
use Author;
use Related;
// Форма редактирование домена
public function index()
{
$domain = ItemPresence::index(Request::getInt('id'));
$domain = ItemPresence::index(Request::getInt('id'));
// Only the site author and staff can edit
// Редактировать может только автор сайта и персонал
@ -37,7 +41,7 @@ class EditItemController extends Controller
}
if (UserData::checkAdmin()) {
Request::getResources()->addBottomScript('/assets/js/admin.js');
Request::getResources()->addBottomScript('/assets/js/catalog.js');
}
return $this->render(
@ -51,6 +55,9 @@ class EditItemController extends Controller
'user' => UserModel::getUser($domain['item_user_id'], 'id'),
'category_arr' => WebModel::getItemTopic($domain['item_id']),
'post_arr' => $item_post_related,
'poll' => PollModel::getQuestion($domain['item_poll']),
'subsections' => RulesItem::getDomains($domain['item_domain']),
'status' => WebModel::getIdStatus($domain['item_id']),
]
],
'item',
@ -87,12 +94,23 @@ class EditItemController extends Controller
$new_user_id = $this->selectAuthor($item['item_user_id'], Request::getPost('user_id'));
if (UserData::checkAdmin()) {
$item_slug = Request::getPost('item_slug');
if ($item_slug != $item['item_slug']) {
if (WebModel::getSlug($slug = $this->getSlug($item_slug))) {
$slug = $slug . "-";
}
}
}
WebModel::edit(
[
'item_id' => $item['item_id'],
'item_url' => $data['url'],
'item_title' => $data['title'],
'item_content' => $data['content'],
'item_slug' => $slug ?? $item['item_slug'],
'item_domain' => RulesItem::getRegisterable($data['url']),
'item_title_soft' => $data['title_soft'] ?? '',
'item_content_soft' => $data['content_soft'] ?? '',
'item_published' => $published,
@ -110,6 +128,7 @@ class EditItemController extends Controller
'item_telephone' => $data['telephone'] ?? null,
'item_email' => $data['email'] ?? null,
'item_vk' => $data['vk'] ?? null,
'item_poll' => $this->selectPoll(Request::getPost('poll_id')),
'item_telegram' => $data['telegram'] ?? null,
]
);

View file

@ -8,29 +8,33 @@ use UserData, Meta;
class HomeController extends Controller
{
protected $limit = 15;
protected $first_page = 1;
public function index($sheet)
public function index()
{
$m = [
'og' => true,
'imgurl' => config('meta.img_path_web'),
'url' => url('main'),
];
return $this->render(
'/item/home',
[
'meta' => Meta::get(__('web.main_title'), __('web.main_desc'), $m),
'meta' => self::metadata(),
'data' => [
'sheet' => $sheet,
'items' => WebModel::feedItem($this->first_page, $this->limit, false, $this->user, false, $sheet, false),
'user_count_site' => UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount($this->user['id']),
'sheet' => 'main',
'items' => WebModel::feedItem(false, false, $this->pageNumber, 'main', false),
'user_count_site' => UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount(),
'audit_count' => UserAreaModel::auditCount(),
]
],
'item',
);
}
public static function metadata()
{
return Meta::get(
__('web.main_title'),
__('web.main_desc'),
[
'og' => true,
'imgurl' => config('meta.img_path_web'),
'url' => url('main'),
]
);
}
}

View file

@ -1,24 +1,29 @@
<?php
namespace Modules\Admin\App;
namespace App\Controllers\Item;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Models\Item\WebModel;
use Img;
use UserData, Img;
class Webs extends Controller
class ImgController extends Controller
{
public function favicon()
{
if (!UserData::checkAdmin()) {
return false;
}
$item_id = Request::getPostInt('id');
$item = WebModel::getItemId($item_id);
notEmptyOrView404($item);
$puth = HLEB_PUBLIC_DIR . Img::PATH['favicons'] . $item["item_domain"] . '.png';
$host = host($item['item_url']);
$puth = HLEB_PUBLIC_DIR . Img::PATH['favicons'] . $host . '.png';
if (!file_exists($puth)) {
$urls = self::getFavicon($item['item_domain']);
$urls = self::getFavicon($host);
copy($urls, $puth);
}
@ -28,17 +33,21 @@ class Webs extends Controller
public static function getFavicon($url)
{
$url = str_replace("https://", '', $url);
//return "https://www.google.com/s2/favicons?domain=" . $url;
// "https://www.google.com/s2/favicons?domain=" . $url;
return "https://favicon.yandex.net/favicon/" . $url;
}
public function screenshot()
{
if (!UserData::checkAdmin()) {
return false;
}
$item_id = Request::getPostInt('id');
$item = WebModel::getItemId($item_id);
notEmptyOrView404($item);
$puth = HLEB_PUBLIC_DIR . Img::PATH['thumbs'] . $item["item_domain"] . '.png';
$puth = HLEB_PUBLIC_DIR . Img::PATH['thumbs'] . host($item['item_url']) . '.png';
if (!file_exists($puth)) {
$urls = self::getScreenshot($item['item_url']);
@ -47,10 +56,10 @@ class Webs extends Controller
return true;
}
public static function getScreenshot($url)
{
return "https://api.screenshotone.com/take?image_width=880&url=" . $url ."&access_key=" . config('integration.sc_access_key');
{
return "https://api.screenshotone.com/take?image_width=880&url=" . $url . "&access_key=" . config('integration.sc_access_key');
}
}

View file

@ -26,7 +26,7 @@ class ReplyController extends Controller
}
insert(
'/_block/form/edit-form-reply',
'/_block/form/edit-reply',
[
'data' => [
'id' => $id,
@ -45,7 +45,7 @@ class ReplyController extends Controller
$item = ItemPresence::index($item_id);
$url = url('website', ['slug' => $item['item_domain']]);
$url = url('website', ['id' => $item['item_id'], 'slug' => $item['item_slug']]);
Validator::Length($content, 6, 555, 'content', $url);
// Access verification
@ -54,7 +54,7 @@ class ReplyController extends Controller
redirect('/');
}
$redirect = url('website', ['slug' => $item['item_domain']]) . '#reply_' . $reply['reply_id'];
$redirect = $url . '#reply_' . $reply['reply_id'];
ReplyModel::edit(
[
@ -77,7 +77,7 @@ class ReplyController extends Controller
$item = ItemPresence::index($item_id);
$website_url = url('website', ['slug' => $item['item_domain']]);
$website_url = url('website', ['id' => $item['item_id'], 'slug' => $item['item_slug']]);
Validator::Length($content, 6, 555, 'content', $website_url);
// We will check for freezing, stop words, the frequency of posting content per day
@ -129,7 +129,7 @@ class ReplyController extends Controller
public function addForma()
{
insert(
'/_block/form/add-form-reply',
'/_block/form/add-reply',
[
'data' => [
'id' => Request::getPostInt('id'),

View file

@ -12,8 +12,8 @@ class UserAreaController extends Controller
public function index()
{
$pagesCount = UserAreaModel::getUserSitesCount($this->user['id']);
$items = UserAreaModel::getUserSites($this->pageNumber, $this->limit, $this->user['id']);
$pagesCount = UserAreaModel::getUserSitesCount();
$items = UserAreaModel::getUserSites($this->pageNumber, $this->limit);
$count_site = UserData::checkAdmin() ? 0 : $pagesCount;
return $this->render(
@ -39,10 +39,10 @@ class UserAreaController extends Controller
// Закладки по сайтам
public function bookmarks()
{
$items = UserAreaModel::bookmarks($this->pageNumber, $this->limit, $this->user['id']);
$pagesCount = UserAreaModel::bookmarksCount($this->user['id']);
$items = UserAreaModel::bookmarks($this->pageNumber, $this->limit);
$pagesCount = UserAreaModel::bookmarksCount();
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount($this->user['id']);
$count_site = UserData::checkAdmin() ? 0 : UserAreaModel::getUserSitesCount();
return $this->render(
'/item/bookmarks',

View file

@ -84,19 +84,16 @@ class MessagesController extends Controller
if ($dialog['dialog_sender_id'] == $this->user['id'] and $val['message_sender_remove']) {
unset($list[$key]);
} else if ($dialog['dialog_sender_id'] != $this->user['id'] and $val['message_recipient_remove']) {
unset($list[$key]);
unset($list[$key]);
} else {
$list[$key]['message_content'] = markdown($val['message_content'], 'text');
$list[$key]['login'] = $recipient_user['login'];
$list[$key]['avatar'] = $recipient_user['avatar'];
$list[$key]['unread'] = $dialog['dialog_recipient_unread'];
// $list[$key]['unread'] = $dialog['dialog_sender_unread'];
}
}
}
Request::getResources()->addBottomStyles('/assets/js/editor/easymde.min.css');
Request::getResources()->addBottomScript('/assets/js/editor/easymde.min.js');
return $this->render(
'/messages/dialog',
[

View file

@ -0,0 +1,52 @@
<?php
namespace App\Controllers\Poll;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Models\{PollModel, ActionModel};
use Meta;
class AddPollController extends Controller
{
// Poll Add Form
// Форма добавление опроса
public function index()
{
return $this->render(
'/poll/add',
[
'meta' => Meta::get(__('app.add_poll')),
'data' => [
'type' => 'add',
]
]
);
}
// Adding a poll
// Добавим опрос
public function create()
{
if (!is_array($data = Request::getPost())) {
return false;
}
$last_id = PollModel::createQuestion($data['title']);
foreach ($data as $key => $val) {
PollModel::createAnswers($key, $val, $last_id);
}
ActionModel::addLogs(
[
'id_content' => $last_id,
'action_type' => 'poll',
'action_name' => 'added',
'url_content' => url('poll', ['id' => $last_id]),
]
);
is_return(__('msg.post_added'), 'success', url('polls'));
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace App\Controllers\Poll;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\PollPresence;
use App\Models\PollModel;
use Access, Meta;
class EditPollController extends Controller
{
// Edit form
// Форма редактирования
public function index()
{
$question = PollPresence::index($id = Request::getInt('id'));
$answers = PollModel::getAnswers($id);
$this->checkingEditPermissions($question);
return $this->render(
'/poll/edit',
[
'meta' => Meta::get(__('app.edit_poll')),
'data' => [
'type' => 'edit',
'question' => $question,
'answers' => $answers,
'answers_count' => PollModel::getAnswersCount($id)
]
]
);
}
public function change()
{
$question = PollPresence::index($id = Request::getPostInt('id'));
$this->checkingEditPermissions($question);
$data = Request::getPost();
PollModel::editTitle($id, $data['title']);
$is_closed = Request::getPost('closed') == 'on' ? 1 : 0;
PollModel::editClosed($id, $is_closed);
foreach ($data as $key => $title) {
if (is_int($key)) {
PollModel::editAnswers($key, $title, $id);
}
}
is_return(__('msg.change_saved'), 'success', url('poll', ['id' => $id]));
}
public function checkingEditPermissions($question)
{
// Only the site author and staff can edit
// Редактировать может только автор сайта и персонал
if (Access::author('poll', $question) === false) {
is_return(__('msg.access_denied'), 'error');
}
return true;
}
public function deletingVariant()
{
return PollModel::delVariant(Request::getPostInt('id'));
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Controllers\Poll;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Models\PollModel;
use Meta;
use App\Traits\Poll;
class PollController extends Controller
{
use Poll;
protected $limit = 15;
public function index()
{
$polls = PollModel::getUserQuestionsPolls($this->pageNumber, $this->limit);
$pagesCount = PollModel::getUserQuestionsPollsCount();
return $this->render(
'/poll/index',
[
'meta' => Meta::get(__('app.polls')),
'data' => [
'pagesCount' => ceil($pagesCount / $this->limit),
'pNum' => $this->pageNumber,
'type' => 'polls',
'polls' => $polls
]
]
);
}
public function poll()
{
$id = Request::getInt('id');
return $this->render(
'/poll/view',
[
'meta' => Meta::get(__('app.poll')),
'data' => [
'type' => 'poll',
'poll' => $this->getPoll($id),
]
]
);
}
public function vote()
{
$question_id = Request::getPostInt('question_id');
$answer_id = Request::getPostInt('answer_id');
return PollModel::vote($question_id, $answer_id);
}
}

View file

@ -4,7 +4,7 @@ namespace App\Controllers\Post;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Models\{SubscriptionModel, ActionModel, PostModel, FacetModel, NotificationModel};
use App\Models\{SubscriptionModel, ActionModel, PostModel, FacetModel, PollModel, NotificationModel};
use App\Services\Integration\{Discord, Telegram};
use App\Services\Сheck\{PostPresence, FacetPresence};
use UploadImage, URLScraper, Meta, UserData;
@ -12,37 +12,45 @@ use UploadImage, URLScraper, Meta, UserData;
use Utopia\Domains\Domain;
use App\Validate\RulesPost;
use App\Traits\Poll;
use App\Traits\Slug;
use App\Traits\Related;
class AddPostController extends Controller
{
use Poll;
use Slug;
use Related;
// Form adding a post / page
// Форма добавление поста / страницы
public function index($type)
public function index()
{
// Adding from page topic
// Добавление со странице темы
$topic_id = Request::getInt('topic_id');
if ($topic_id) {
$topic = FacetPresence::index($topic_id, 'id', 'topic');
}
// Adding from page topic / blog
// Добавление со странице темы / блога
$facet_id = Request::getInt('facet_id');
$blog = FacetModel::getFacetsUser('blog');
$facets = FacetModel::getTeamFacets('blog');
if ($facet_id) {
$facet = FacetPresence::all($facet_id);
if ($facet['facet_type'] == 'topic') {
$topic = FacetPresence::index($facet_id, 'id', 'topic');
} elseif ($facet['facet_type'] == 'blog' && $facet['facet_user_id'] == $this->user['id']) {
$blog = FacetPresence::index($facet_id, 'id', 'blog');
}
}
return $this->render(
'/post/add',
[
'meta' => Meta::get(__('app.add_' . $type)),
'meta' => Meta::get(__('app.add_post')),
'data' => [
'facets' => ['topic' => $topic ?? false],
'blog' => array_merge($facets, $blog),
'post_arr' => PostModel::postRelatedAll(),
'type' => 'add',
'topic' => $topic ?? false,
'blog' => $blog ?? false,
'showing-blog' => array_merge(FacetModel::getTeamFacets('blog'), FacetModel::getFacetsUser('blog')),
'post_arr' => PostModel::postRelatedAll(),
'type' => 'add',
'count_poll' => PollModel::getUserQuestionsPollsCount(),
]
]
);
@ -83,7 +91,7 @@ class AddPostController extends Controller
// Post cover
// Обложка поста
if (!empty($_FILES['images']['name'])) {
$post_img = UploadImage::coverPost($_FILES['images'], 0, $redirect, $this->user['id']);
$post_img = UploadImage::coverPost($_FILES['images'], 0, $redirect);
}
if (PostModel::getSlug($slug = $this->getSlug($fields['post_title']))) {
@ -93,7 +101,9 @@ class AddPostController extends Controller
$post_related = $this->relatedPost();
$translation = $fields['translation'] ?? false;
$post_draft = $fields['post_draft'] ?? false;
$post_draft = $fields['draft'] ?? false;
$post_nsfw = $fields['nsfw'] ?? false;
$post_hidden = $fields['hidden'] ?? false;
$closed = $fields['closed'] ?? false;
$top = $fields['top'] ?? false;
@ -111,6 +121,8 @@ class AddPostController extends Controller
'post_type' => $type,
'post_translation' => $translation == 'on' ? 1 : 0,
'post_draft' => $post_draft == 'on' ? 1 : 0,
'post_nsfw' => $post_nsfw == 'on' ? 1 : 0,
'post_hidden' => $post_hidden == 'on' ? 1 : 0,
'post_ip' => Request::getRemoteAddress(),
'post_published' => ($trigger === false) ? 0 : 1,
'post_user_id' => $this->user['id'],
@ -119,6 +131,7 @@ class AddPostController extends Controller
'post_tl' => $fields['content_tl'] ?? 0,
'post_closed' => $closed == 'on' ? 1 : 0,
'post_top' => $top == 'on' ? 1 : 0,
'post_poll' => $this->selectPoll(Request::getPost('poll_id')),
]
);
@ -160,8 +173,7 @@ class AddPostController extends Controller
// Since this is for the post, we will get a preview and analysis of the domain ...
public function addUrl($post_url)
{
$parse = parse_url($post_url);
$domain = new Domain($parse['host']);
$domain = new Domain(host($post_url));
$site = [
'og_img' => self::grabOgImg($post_url),
@ -176,23 +188,18 @@ class AddPostController extends Controller
public function grabMeta()
{
$url = Request::getPost('uri');
$meta = new URLScraper($url);
$result = URLScraper::get($url);
$meta->parse();
$metaData = $meta->finalize();
return json_encode($metaData);
return json_encode($result, JSON_PRETTY_PRINT);
}
// Getting Open Graph Protocol Data
// Получаем данные Open Graph Protocol
public static function grabOgImg($post_url)
{
$meta = new URLScraper($post_url);
$meta->parse();
$metaData = $meta->finalize();
$meta = URLScraper::get($post_url);
return UploadImage::thumbPost($metaData->image);
return UploadImage::thumbPost($meta['image']);
}
// Recommend post

View file

@ -6,10 +6,11 @@ use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\PostPresence;
use App\Models\User\UserModel;
use App\Models\{FacetModel, PostModel};
use App\Models\{FacetModel, PostModel, PollModel};
use UploadImage, Meta, Access, UserData;
use App\Traits\Slug;
use App\Traits\Poll;
use App\Traits\Author;
use App\Traits\Related;
@ -18,6 +19,7 @@ use App\Validate\RulesPost;
class EditPostController extends Controller
{
use Slug;
use Poll;
use Author;
use Related;
@ -49,6 +51,7 @@ class EditPostController extends Controller
'topic_arr' => PostModel::getPostFacet($post['post_id'], 'topic'),
'blog_arr' => PostModel::getPostFacet($post['post_id'], 'blog'),
'section_arr' => PostModel::getPostFacet($post['post_id'], 'section'),
'poll' => PollModel::getQuestion($post['post_poll']),
]
]
);
@ -81,7 +84,7 @@ class EditPostController extends Controller
// Post cover
if (!empty($_FILES['images']['name'])) {
$post_img = UploadImage::coverPost($_FILES['images'], $post, $redirect, $this->user['id']);
$post_img = UploadImage::coverPost($_FILES['images'], $post, $redirect);
}
$post_img = $post_img ?? $post['post_content_img'];
@ -120,7 +123,11 @@ class EditPostController extends Controller
'post_merged_id' => $post_merged_id ?? 0,
'post_tl' => Request::getPostInt('content_tl'),
'post_closed' => Request::getPost('closed') == 'on' ? 1 : 0,
'post_nsfw' => Request::getPost('nsfw') == 'on' ? 1 : 0,
'post_hidden' => Request::getPost('hidden') == 'on' ? 1 : 0,
'post_top' => Request::getPost('top') == 'on' ? 1 : 0,
'post_poll' => $this->selectPoll(Request::getPost('poll_id')),
'post_modified' => date("Y-m-d H:i:s"),
]
);
@ -165,7 +172,7 @@ class EditPostController extends Controller
}
PostModel::setPostImgRemove($post['post_id']);
UploadImage::coverPostRemove($post['post_content_img'], $this->user['id']);
UploadImage::coverPostRemove($post['post_content_img']);
is_return(__('msg.cover_removed'), 'success', url('content.edit', ['type' => 'post', 'id' => $post['post_id']]));
}
@ -176,13 +183,13 @@ class EditPostController extends Controller
$type = Request::get('type');
$id = Request::getInt('id');
if (!in_array($type, ['post-telo', 'answer'])) {
if (!in_array($type, ['post-telo', 'comment'])) {
return false;
}
$img = $_FILES['image'];
if ($_FILES['image']['name']) {
return json_encode(array('data' => array('filePath' => UploadImage::postImg($img, $user_id, $type, $id))));
return json_encode(['data' => ['filePath' => UploadImage::postImg($img, $type, $id)]]);
}
return false;

View file

@ -6,15 +6,19 @@ use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Services\Сheck\PostPresence;
use App\Services\Сheck\FacetPresence;
use App\Models\{PostModel, AnswerModel, CommentModel, SubscriptionModel, FeedModel};
use Meta, UserData, Access, Img;
use App\Services\Meta\Post;
use App\Services\Tree\BuildTree;
use App\Models\{PostModel, CommentModel, SubscriptionModel, FeedModel};
use Meta, UserData;
use App\Traits\Views;
use App\Traits\Poll;
use App\Traits\LastDataModified;
class PostController extends Controller
{
use Views;
use Poll;
use LastDataModified;
protected $limit = 25;
@ -25,6 +29,7 @@ class PostController extends Controller
{
$slug = Request::get('slug');
$id = Request::getInt('id');
$sorting = Request::getGet('sort');
$content = self::presence($type, $id, $slug);
@ -45,39 +50,23 @@ class PostController extends Controller
redirect(url('facet.article', ['facet_slug' => 'info', 'slug' => $content['post_slug']]));
}
// Q&A (post_feature == 1) or Discussiona
$content['amount_content'] = ($content['post_feature'] == 0) ? $content['post_comments_count'] + $content['post_answers_count'] : $content['post_answers_count'];
// Get replies and comments on the post
$answers = $this->answersPost($content['post_id'], $content['post_feature'], $sorting = Request::getGet('sort'));
$description = (fragment($content['post_content'], 250) == '') ? strip_tags($content['post_title']) : fragment($content['post_content'], 250);
$this->stylesHead($content, $blog);
if ($content['post_related']) {
$related_posts = PostModel::postRelated($content['post_related']);
}
$m = [
'published_time' => $content['post_date'],
'type' => 'article',
'og' => true,
'imgurl' => self::images($content),
'url' => post_slug($content['post_id'], $content['post_slug']),
];
// Sending Last-Modified and handling HTTP_IF_MODIFIED_SINCE
$this->getDataModified($content['post_modified']);
$comments = CommentModel::getCommentsPost($content['post_id'], $content['post_feature'], $sorting);
if ($type == 'post') {
return $this->render(
'/post/post-view',
[
'meta' => Meta::get(strip_tags($content['post_title']), $description, $m),
'meta' => Post::metadata($content),
'data' => [
'post' => $content,
'answers' => $answers,
'comments' => BuildTree::index(0, $comments),
'recommend' => PostModel::postSimilars($content['post_id'], $facets[0]['facet_id'] ?? null),
'related_posts' => $related_posts ?? '',
'post_signed' => SubscriptionModel::getFocus($content['post_id'], 'post'),
@ -88,6 +77,7 @@ class PostController extends Controller
'sorting' => $sorting ?? null,
'sheet' => 'article',
'type' => 'post',
'poll' => $this->getPoll($content['post_poll']),
]
]
);
@ -96,15 +86,10 @@ class PostController extends Controller
$slug_facet = Request::get('facet_slug');
$facet = FacetPresence::index($slug_facet, 'slug', 'section');
$m = [
'og' => false,
'url' => url('facet.article', ['facet_slug' => $facet['facet_slug'], 'slug' => $content['post_slug']]),
];
return $this->render(
'/post/page-view',
[
'meta' => Meta::get($content['post_title'] . ' - ' . __('app.page'), $description . ' (' . $facet['facet_title'] . ' - ' . __('app.page') . ')', $m),
'meta' => Post::metadata($content),
'data' => [
'sheet' => 'page',
'type' => $type,
@ -116,41 +101,6 @@ class PostController extends Controller
);
}
public function stylesHead($content, $blog)
{
Request::getResources()->addBottomScript('/assets/js/share/goodshare.min.js');
Request::getResources()->addBottomScript('/assets/js/dialog/dialog.js');
if ($content['post_is_deleted'] == 1) {
Request::getHead()->addMeta('robots', 'noindex');
}
if ($this->user['id'] > 0 && $content['post_closed'] == 0) {
Request::getResources()->addBottomStyles('/assets/js/editor/easymde.min.css');
Request::getResources()->addBottomScript('/assets/js/editor/easymde.min.js');
}
}
// Get replies and comments on the post
// Получим ответы и комментарии на пост
public function answersPost($post_id, $post_feature, $sorting)
{
$post_answers = AnswerModel::getAnswersPost($post_id, $post_feature, $sorting);
$answers = [];
foreach ($post_answers as $ind => $row) {
if (strtotime($row['answer_modified']) < strtotime($row['answer_date'])) {
$row['edit'] = 1;
}
// TODO: N+1 см. AnswerModel()
$row['comments'] = CommentModel::getCommentsAnswer($row['answer_id']);
$answers[$ind] = $row;
}
return $answers;
}
public static function presence($type, $id, $slug)
{
// Check id and get content data
@ -231,21 +181,6 @@ class PostController extends Controller
);
}
// Define an image for meta tags
// Определим изображение для meta- тегов
public static function images($content)
{
$content_img = config('meta.img_path');
if ($content['post_content_img']) {
$content_img = Img::PATH['posts_cover'] . $content['post_content_img'];
} elseif ($content['post_thumb_img']) {
$content_img = Img::PATH['posts_thumb'] . $content['post_thumb_img'];
}
return $content_img;
}
// Last 5 pages by content id
// Последние 5 страниц по id контенту
public function last($content_id)

View file

@ -30,7 +30,7 @@ class SearchController extends Controller
$q = Request::getGet('q');
$type = Request::getGet('cat');
if (!in_array($type, ['post', 'website', 'answer'])) {
if (!in_array($type, ['post', 'website', 'comment'])) {
$type = 'post';
}
@ -44,6 +44,7 @@ class SearchController extends Controller
}
$results = SearchModel::getSearch($this->pageNumber, $this->limit, $q, $type);
$count_results = SearchModel::getSearchCount($q, $type);
$user_id = UserData::getUserId();

View file

@ -6,7 +6,7 @@ use Hleb\Constructor\Handlers\Request;
use App\Services\Meta\Profile;
use App\Controllers\Controller;
use App\Models\User\{UserModel, BadgeModel};
use App\Models\{FacetModel, FeedModel, AnswerModel, CommentModel, PostModel, IgnoredModel};
use App\Models\{FacetModel, FeedModel, CommentModel, PostModel, IgnoredModel};
use UserData;
use App\Traits\Views;
@ -58,7 +58,7 @@ class ProfileController extends Controller
$this->indexing($profile['id']);
return $this->render(
'/user/profile/post',
'/user/profile/posts',
[
'meta' => Profile::metadata('profile_posts', $profile),
'data' => array_merge($this->sidebar($pagesCount, $profile), ['posts' => $posts]),
@ -71,26 +71,16 @@ class ProfileController extends Controller
{
$profile = $this->profile();
$answers = AnswerModel::userAnswers($this->pageNumber, $this->limit, $profile['id'], $this->user['id']);
$answerCount = AnswerModel::userAnswersCount($profile['id']);
$comments = CommentModel::userComments($this->pageNumber, $this->limit, $profile['id'], $this->user['id']);
$commentCount = CommentModel::userCommentsCount($profile['id']);
$pagesCount = $answerCount + $commentCount;
$mergedArr = array_merge($comments, $answers);
usort($mergedArr, function ($a, $b) {
return ($b['comment_date'] ?? $b['answer_date']) <=> ($a['comment_date'] ?? $a['answer_date']);
});
$comments = CommentModel::userComments($this->pageNumber, $profile['id'], $this->user['id']);
$commentsCount = CommentModel::userCommentsCount($profile['id']);
$this->indexing($profile['id']);
return $this->render(
'/user/profile/comment',
'/user/profile/comments',
[
'meta' => Profile::metadata('profile_comments', $profile),
'data' => array_merge($this->sidebar($pagesCount, $profile), ['comments' => $mergedArr]),
'data' => array_merge($this->sidebar($commentsCount, $profile), ['comments' => $comments]),
]
);
}
@ -146,12 +136,16 @@ class ProfileController extends Controller
return true;
}
// Index profile or not
public function indexing($profile_id)
{
$amount = UserModel::contentCount($profile_id, 'active');
if (($amount['count_answers'] + $amount['count_comments']) < 3) {
if (($amount['count_comments']) < 3) {
Request::getHead()->addMeta('robots', 'noindex');
}
if (UserModel::isDeleted($profile_id)) {
Request::getHead()->addMeta('robots', 'noindex');
}
}

View file

@ -5,8 +5,8 @@ namespace App\Controllers\User;
use Hleb\Constructor\Handlers\Request;
use App\Controllers\Controller;
use App\Models\User\{SettingModel, UserModel};
use App\Models\IgnoredModel;
use UploadImage, Meta, UserData, Img;
use App\Models\{IgnoredModel, AuthModel, ActionModel};
use UploadImage, Session, Meta, UserData, Img, Html, SendEmail;
use App\Validate\RulesUserSetting;
@ -32,6 +32,9 @@ class SettingController extends Controller
case 'ignored':
return $this->ignored();
break;
case 'deletion':
return $this->deletion();
break;
default:
return $this->settingForm();
break;
@ -60,12 +63,26 @@ class SettingController extends Controller
// Форма настройки профиля
function settingForm()
{
Request::getResources()->addBottomScript('/assets/js/dialog/dialog.js');
$new = SettingModel::getNewEmail();
$email = $new['email'] ?? null;
if ($code = Request::getGet('newemail')) {
if (SettingModel::available($code)) {
SettingModel::editEmail($email);
is_return(__('msg.change_saved'), 'success', url('setting'));
}
}
return $this->render(
'/user/setting/setting',
[
'meta' => Meta::get(__('app.setting')),
'data' => [
'user' => UserModel::getUser($this->user['login'], 'slug'),
'user' => UserModel::getUser($this->user['login'], 'slug'),
'new_email' => $email,
]
]
);
@ -86,6 +103,7 @@ class SettingController extends Controller
'activated' => $user['activated'],
'limiting_mode' => $user['limiting_mode'],
'scroll' => Request::getPost('scroll') == 'on' ? 1 : 0,
'nsfw' => Request::getPost('nsfw') == 'on' ? 1 : 0,
'trust_level' => $user['trust_level'],
'updated_at' => date('Y-m-d H:i:s'),
'color' => Request::getPostString('color', '#339900'),
@ -199,7 +217,6 @@ class SettingController extends Controller
);
}
function ignored()
{
return $this->render(
@ -213,6 +230,17 @@ class SettingController extends Controller
);
}
function deletion()
{
return $this->render(
'/user/setting/deletion',
[
'meta' => Meta::get(__('app.delete_profile')),
'data' => []
]
);
}
function notificationEdit()
{
SettingModel::setNotifications(
@ -222,10 +250,46 @@ class SettingController extends Controller
'setting_email_appealed' => Request::getPostInt('setting_email_appealed'),
'setting_email_post' => 0,
'setting_email_answer' => 0,
'setting_email_comment' => 0,
]
);
is_return(__('msg.change_saved'), 'success', '/setting/notifications');
}
function newEmail()
{
$email = Request::getPost('email');
if (RulesUserSetting::rulesNewEmail($email) === false) {
return json_encode('error');
}
if (is_array(AuthModel::checkRepetitions($email, 'email'))) {
return json_encode('repeat');
}
$code = Html::randomString('crypto', 20);
SettingModel::setNewEmail($email, $code);
SendEmail::mailText($this->user['id'], 'new.email', ['link' => '/setting?newemail=' . $code, 'new_email' => $email]);
return json_encode('success');
}
public function deleteActivation()
{
SettingModel::deletionUser($this->user['id']);
ActionModel::addLogs(
[
'id_content' => $this->user['id'],
'action_type' => 'profile',
'action_name' => 'deleted',
'url_content' => url('profile', ['login' => $this->user['login']]),
]
);
Session::logout();
}
}

View file

@ -49,10 +49,10 @@ class UserController extends Controller
$result = [];
foreach ($favorites as $ind => $row) {
if ($row['action_type'] == 'post') {
$row['answer_post_id'] = $row['post_id'];
$row['comment_post_id'] = $row['post_id'];
}
$row['post'] = PostModel::getPost($row['answer_post_id'], 'id', $this->user);
$row['post'] = PostModel::getPost($row['comment_post_id'], 'id', $this->user);
$result[$ind] = $row;
}

View file

@ -12,7 +12,7 @@ class Access
$type = Request::get('type');
// TODO: Изменим поля в DB, чтобы использовать limitContent для messages и invitation:
if (in_array($type, ['post', 'amswer', 'comment', 'item'])) {
if (in_array($type, ['post', 'amswer', 'comment', 'item', 'poll'])) {
if (self::limitContent($type) === false) {
Msg::add(__('msg.limit_day'), 'error');
redirect('/');

View file

@ -37,13 +37,11 @@ class Html
}
// Blog, topic or category
public static function addPost($facet)
public static function addPost($facet_id)
{
$url_add = url('content.add', ['type' => 'post']);
if (!empty($facet)) {
if ($facet['facet_user_id'] == UserData::getUserId() || $facet['facet_type'] == 'topic') {
$url_add = $url_add . '/' . $facet['facet_id'];
}
if (!empty($facet_id)) {
$url_add = $url_add . '/' . $facet_id;
}
return '<a title="' . __('app.add_post') . '" href="' . $url_add . '" class="sky"><svg class="icons"><use xlink:href="/assets/svg/icons.svg#plus"></use></svg></a>';
@ -78,7 +76,7 @@ class Html
return ((int)$a[2] . " " . $months[$later] . " " . $a[0]);
}
// Voting for posts, replies, comments and sites
// Voting for posts, replies, answer and sites
public static function votes($content, $type, $icon = 'heart')
{
$count = $content[$type . '_votes'] > 0 ? $content[$type . '_votes'] : '';
@ -101,10 +99,10 @@ class Html
public static function favorite($content_id, $type, $tid, $heading = '')
{
$head = ($heading == 'heading') ? __('app.save') : '';
$html = '<a class="click-no-auth gray-600"><svg class="icons"><use xlink:href="/assets/svg/icons.svg#bookmark"></use></svg>' . $head . '</a>';
$html = '<div class="click-no-auth gray-600"><svg class="icons"><use xlink:href="/assets/svg/icons.svg#bookmark"></use></svg>' . $head . '</div>';
if (UserData::getAccount()) {
$active = $tid ? 'active' : 'gray-600';
$html = '<a id="favorite_' . $content_id . '" class="add-favorite ' . $active . '" data-id="' . $content_id . '" data-type="' . $type . '"><svg class="icons"><use xlink:href="/assets/svg/icons.svg#bookmark"></use></svg></i>' . $head . '</a>';
$html = '<div id="favorite_' . $content_id . '" class="add-favorite ' . $active . '" data-id="' . $content_id . '" data-type="' . $type . '"><svg class="icons"><use xlink:href="/assets/svg/icons.svg#bookmark"></use></svg></i>' . $head . '</div>';
}
return $html;

View file

@ -45,17 +45,17 @@ class Img
}
// Icons, screenshots associated with the site
public static function website($domain, $type, $alt, $css = '')
public static function website($type, $host, $css = '')
{
$path = ($type == 'thumbs') ? self::PATH['thumbs'] : self::PATH['favicons'];
$path = ($type == 'thumb') ? self::PATH['thumbs'] : self::PATH['favicons'];
$itemprop = ($type == 'thumbs') ? 'itemprop="image"' : '';
$itemprop = ($type == 'thumb') ? 'itemprop="image"' : '';
if (file_exists(HLEB_PUBLIC_DIR . $path . $domain . '.png')) {
return '<img ' . $itemprop . ' class="' . $css . '" src="' . $path . $domain . '.png" title="' . $alt . '" alt="' . $alt . '">';
if (file_exists(HLEB_PUBLIC_DIR . $path . $host . '.png')) {
return '<img ' . $itemprop . ' class="' . $css . '" src="' . $path . $host . '.png" title="' . $host . '" alt="' . $host . '">';
}
return '<img class="mr5 ' . $css . '" src="' . $path . 'no-link.png" title="' . $alt . '" alt="' . $alt . '">';
return '<img class="mr5 ' . $css . '" src="' . $path . 'no-link.png" title="' . $host . '" alt="' . $host . '">';
}
// Cover of users, blog

View file

@ -1,55 +0,0 @@
<?php
class Limiter
{
private $route;
public function __construct(string $route)
{
$this->route = $route;
if (!!$this->getSessionCache("last_session_request")) return;
$this->setSessionCache("request_cnt", 1);
$this->setSessionCache("last_session_request", time());
}
private function setSessionCache(string $key, $value)
{
$_SESSION["cache"][$this->route][$key] = $value;
}
private function getSessionCache(string $key)
{
return $_SESSION["cache"][$this->route][$key] ?? null;
}
public function limitRequests(int $max_requests, int $time_interval, callable $handle_time_exceeded)
{
$limit_time = time() - $time_interval;
$request_cnt = $this->getSessionCache("request_cnt");
$last_session_request = $this->getSessionCache("last_session_request");
$is_flooded = $last_session_request > $limit_time;
if (!$is_flooded) {
$this->setSessionCache("request_cnt", 1);
$this->setSessionCache("last_session_request", time());
return;
}
if ($request_cnt < $max_requests) {
$this->setSessionCache("request_cnt", $request_cnt + 1);
return;
}
$time_left = $last_session_request - $limit_time;
$handle_time_exceeded($time_left);
}
}

View file

@ -34,7 +34,16 @@ class Meta
. '<meta property="og:image:width" content="820">'
. '<meta property="og:image:height" content="320">';
}
$output .= '<meta name="twitter:card" content="summary">'
. '<meta name="twitter:title" content="' . $title . '">'
. '<meta name="twitter:url" content="' . config('meta.url') . $m['url'] . '">'
. '<meta property="twitter:description" content="' . $description . '">';
if (!empty($m['imgurl'])) { $output .= '<meta property="twitter:image" content="' . config('meta.url') . $m['imgurl'] . '">'; }
}
}
return $output;

View file

@ -3,6 +3,10 @@
use App\Models\User\{SettingModel, UserModel};
use App\Exception\AutorizationException;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
class SendEmail
{
public static function mailText($uid, $type, array $variables = [])
@ -38,6 +42,11 @@ class SendEmail
$subject = __('mail.activate_email_subject', ['name' => config('meta.name')]);
$message = __('mail.activate_email_message', ['url' => $url . $variables['link']]);
break;
case 'new.email':
$user_email = $variables['new_email'];
$subject = __('mail.new_email_subject', ['name' => config('meta.name')]);
$message = __('mail.new_email_message', ['url' => $url . $variables['link']]);
break;
case 'invite.reg':
$user_email = $variables['invitation_email'];
$subject = __('mail.invite_reg_subject', ['name' => config('meta.name')]);
@ -57,20 +66,45 @@ class SendEmail
{
if (config('integration.smtp')) {
$mailSMTP = new SendMailSmtpClass(config('integration.smtp_user'), config('integration.smtp_pass'), 'ssl://' . config('integration.smtp_host'), config('integration.smtp_port'), "UTF-8");
$mail = new PHPMailer(true);
$from = array(
config('meta.name'), // Имя отправителя
config('integration.smtp_user') // почта отправителя
);
try {
// Server settings
// $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
$mail->isSMTP(); //Send using SMTP
$mail->Host = config('integration.smtp_host'); //Set the SMTP server to send through
$mail->SMTPAuth = true; //Enable SMTP authentication
$mail->Username = config('integration.smtp_user'); //SMTP username
$mail->Password = config('integration.smtp_pass'); //SMTP password
$mail->SMTPSecure = 'ssl'; // PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
$mail->Port = config('integration.smtp_port'); //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
$result = $mailSMTP->send($email, $subject, $message, $from);
/* $mail->SMTPOptions = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]; */
if ($result === true) {
echo "Done";
} else {
throw AutorizationException::Smtp("Error - " . $result);
}
$mail->CharSet = 'utf-8';
//Recipients
$mail->setFrom(config('integration.smtp_user'), config('meta.name'));
$mail->addAddress($email); //Name is optional
//Content
$mail->isHTML(true); //Set email format to HTML
$mail->Subject = $subject;
$mail->Body = $message;
$mail->send();
return true;
} catch (Exception $e) {
throw AutorizationException::Smtp("Message could not be sent. Mailer Error: {$mail->ErrorInfo}");
}
} else {
$mail = new \Phphleb\Muller\StandardMail(false);
$mail->setNameFrom(config('meta.name')); // вот тут было длинное

View file

@ -1,275 +0,0 @@
<?php
/**
* https://github.com/Ipatov/SendMailSmtpClass
* @author Ipatov Evgeniy <admin@vk-book.ru>
* @version 1.2
*/
use App\Exception\AutorizationException;
class SendMailSmtpClass
{
/**
*
* @var string $smtp_username - логин
* @var string $smtp_password - пароль
* @var string $smtp_host - хост
* @var array $smtp_from - от кого
* @var integer $smtp_port - порт
* @var string $smtp_charset - кодировка
* @var string $boundary - разделитель содержимого письма(для отправки файлов)
* @var bool $addFile - содержит письмо файл или нет
* @var string $multipart - заголовки для письма с файлами
* @var array $arrayCC - массив получателей копии письма
* @var array $arrayBCC - массив получателей скрытой копии письма
*
*/
public $smtp_username;
public $smtp_password;
public $smtp_host;
public $smtp_from;
public $smtp_port;
public $smtp_charset;
public $boundary;
public $addFile = false;
public $multipart;
public $arrayCC;
public $arrayBCC;
public function __construct($smtp_username, $smtp_password, $smtp_host, $smtp_port = 25, $smtp_charset = "utf-8")
{
$this->smtp_username = $smtp_username;
$this->smtp_password = $smtp_password;
$this->smtp_host = $smtp_host;
$this->smtp_port = $smtp_port;
$this->smtp_charset = $smtp_charset;
// разделитель файлов
$this->boundary = "--" . md5(uniqid(time()));
$this->multipart = "";
}
/**
* Отправка письма
*
* @param string $mailTo - получатель письма
* @param string $subject - тема письма
* @param string $message - тело письма
* @param array $smtp_from - отправитель. Массив с именем и e-mail
*
* @return bool|string В случаи отправки вернет true, иначе текст ошибки
*
*/
function send($mailTo, $subject, $message, $smtp_from)
{
// подготовка содержимого письма к отправке
$contentMail = $this->getContentMail($subject, $message, $smtp_from, $mailTo);
try {
if (!$socket = @fsockopen($this->smtp_host, $this->smtp_port, $errorNumber, $errorDescription, 30)) {
throw AutorizationException::Smtp($errorNumber . "." . $errorDescription);
}
if (!$this->_parseServer($socket, "220")) {
throw AutorizationException::Smtp('Connection error');
}
$server_name = $_SERVER["SERVER_NAME"];
fputs($socket, "EHLO $server_name\r\n");
if (!$this->_parseServer($socket, "250")) {
// если сервер не ответил на EHLO, то отправляем HELO
fputs($socket, "HELO $server_name\r\n");
if (!$this->_parseServer($socket, "250")) {
fclose($socket);
throw AutorizationException::Smtp('Error of command sending: HELO');
}
}
fputs($socket, "AUTH LOGIN\r\n");
if (!$this->_parseServer($socket, "334")) {
fclose($socket);
throw AutorizationException::Smtp('Autorization error');
}
fputs($socket, base64_encode($this->smtp_username) . "\r\n");
if (!$this->_parseServer($socket, "334")) {
fclose($socket);
throw AutorizationException::Smtp('Autorization error');
}
fputs($socket, base64_encode($this->smtp_password) . "\r\n");
if (!$this->_parseServer($socket, "235")) {
fclose($socket);
throw AutorizationException::Smtp('Autorization error');
}
fputs($socket, "MAIL FROM: <" . $smtp_from[1] . ">\r\n");
if (!$this->_parseServer($socket, "250")) {
fclose($socket);
throw AutorizationException::Smtp('Error of command sending: MAIL FROM');
}
$mailTo = str_replace(" ", "", $mailTo);
$emails_to_array = explode(',', $mailTo);
foreach ($emails_to_array as $email) {
fputs($socket, "RCPT TO: <{$email}>\r\n");
if (!$this->_parseServer($socket, "250")) {
fclose($socket);
throw AutorizationException::Smtp('Error of command sending: RCPT TO');
}
}
// если есть кому отправить копию
if (!empty($this->arrayCC)) {
foreach ($this->arrayCC as $emailCC) {
fputs($socket, "RCPT TO: <{$emailCC}>\r\n");
if (!$this->_parseServer($socket, "250")) {
fclose($socket);
throw AutorizationException::Smtp('Error of command sending: RCPT TO');
}
}
}
// если есть кому отправить скрытую копию
if (!empty($this->arrayBCC)) {
foreach ($this->arrayBCC as $emailBCC) {
fputs($socket, "RCPT TO: <{$emailBCC}>\r\n");
if (!$this->_parseServer($socket, "250")) {
fclose($socket);
throw AutorizationException::Smtp('Error of command sending: RCPT TO');
}
}
}
fputs($socket, "DATA\r\n");
if (!$this->_parseServer($socket, "354")) {
fclose($socket);
throw AutorizationException::Smtp('Error of command sending: DATA');
}
fputs($socket, $contentMail . "\r\n.\r\n");
if (!$this->_parseServer($socket, "250")) {
fclose($socket);
throw AutorizationException::Smtp("E-mail didn't sent");
}
fputs($socket, "QUIT\r\n");
fclose($socket);
} catch (Exception $e) {
return $e->getMessage();
}
return true;
}
// добавление файла в письмо
public function addFile($path)
{
$file = @fopen($path, "rb");
if (!$file) {
throw AutorizationException::Smtp("File `{$path}` didn't open");
}
$data = fread($file, filesize($path));
fclose($file);
$filename = basename($path);
$multipart = "\r\n--{$this->boundary}\r\n";
$multipart .= "Content-Type: application/octet-stream; name=\"$filename\"\r\n";
$multipart .= "Content-Transfer-Encoding: base64\r\n";
$multipart .= "Content-Disposition: attachment; filename=\"$filename\"\r\n";
$multipart .= "\r\n";
$multipart .= chunk_split(base64_encode($data));
$this->multipart .= $multipart;
$this->addFile = true;
}
// парсинг ответа сервера
private function _parseServer($socket, $response)
{
$responseServer = $response;
while (@substr($responseServer, 3, 1) != ' ') {
if (!($responseServer = fgets($socket, 256))) {
return false;
}
}
if (!(substr($responseServer, 0, 3) == $response)) {
return false;
}
return true;
}
// подготовка содержимого письма
private function getContentMail($subject, $message, $smtp_from, $mailTo)
{
// если кодировка windows-1251, то перекодируем тему
if (strtolower($this->smtp_charset) == "windows-1251") {
$subject = iconv('utf-8', 'windows-1251', $subject);
}
$contentMail = "Date: " . date("D, d M Y H:i:s") . " UT\r\n";
$contentMail .= 'Subject: =?' . $this->smtp_charset . '?B?' . base64_encode($subject) . "=?=\r\n";
// заголовок письма
$headers = "MIME-Version: 1.0\r\n";
// кодировка письма
if ($this->addFile) {
// если есть файлы
$headers .= "Content-Type: multipart/mixed; boundary=\"{$this->boundary}\"\r\n";
} else {
$headers .= "Content-type: text/html; charset={$this->smtp_charset}\r\n";
}
// $headers .= "From: {$smtp_from[0]} <{$smtp_from[1]}>\r\n"; // от кого письмо
$headers .= 'From: ' . '=?UTF-8?B?' . base64_encode($smtp_from[0]) . '?= ' . '<' . $smtp_from[1] . '>' . "\n";
$headers .= "To: " . $mailTo . "\r\n"; // кому
// если есть кому отправить копию
if (!empty($this->arrayCC)) {
foreach ($this->arrayCC as $emailCC) {
$headers .= "Cc: " . $emailCC . "\r\n"; // кому копию
}
}
// если есть кому отправить копию
if (!empty($this->arrayBCC)) {
foreach ($this->arrayBCC as $emailBCC) {
$headers .= "Bcc: " . $emailBCC . "\r\n"; // кому копию
}
}
$contentMail .= $headers . "\r\n";
if ($this->addFile) {
// если есть файлы
$multipart = "--{$this->boundary}\r\n";
$multipart .= "Content-Type: text/html; charset=utf-8\r\n";
$multipart .= "Content-Transfer-Encoding: base64\r\n";
$multipart .= "\r\n";
$multipart .= chunk_split(base64_encode($message));
// файлы
$multipart .= $this->multipart;
$multipart .= "\r\n--{$this->boundary}--\r\n";
$contentMail .= $multipart;
} else {
$contentMail .= $message . "\r\n";
}
// если кодировка windows-1251, то все письмо перекодируем
if (strtolower($this->smtp_charset) == "windows-1251") {
$contentMail = iconv('utf-8', 'windows-1251', $contentMail);
}
return $contentMail;
}
// добавлении получателя копии
public function toCopy($email)
{
$this->arrayCC[] = $email;
}
// добавлении получателя скрытой копии
public function toHideCopy($email)
{
$this->arrayBCC[] = $email;
}
}

15
app/Core/Session.php Normal file
View file

@ -0,0 +1,15 @@
<?php
class Session
{
public static function logout()
{
if (!isset($_SESSION)) {
session_start();
}
session_destroy();
setcookie("remember", "", time() - 3600, "/", httponly: true);
redirect('/');
}
}

View file

@ -1,246 +1,31 @@
<?php
// MIT License
// Copyright 2018 Bert Maurau
// https://github.com/tommyku/php-html-meta-parser
// FIX: UTF (test: https://lenta.ru/news/2021/09/09/fantastic_russians/)
use Symfony\Component\DomCrawler\Crawler;
use GuzzleHttp\Client;
class URLScraper
{
private static $STATUS = [
"initialized" => 0,
"success" => 1,
"fail" => 2
];
public static function get($url)
{
// Create a client to make the HTTP request
$client = new \GuzzleHttp\Client();
$response = $client->get($url);
$html = (string) $response->getBody();
private $metaData;
private $url;
private $html;
private $status;
private $meta;
$crawler = new Crawler($html);
/**
* __construct
*
* Require the url of the webpage for meta data extraction
*
* @access public
* @param string $url
*/
public function __construct($url)
{
$this->url = $url;
$this->metaData = new StdClass;
$this->metaData->title = "";
$this->metaData->description = "";
$this->metaData->image = "";
$this->initialized();
}
$titleNode = $crawler->filter('title');
$descriptionNode = $crawler->filter('meta[name="description"]');
$imageNode = $crawler->filter('meta[property="og:image"]');
$title = $titleNode->count() ? $titleNode->first()->text() : null;
$description = $descriptionNode->count() ? $descriptionNode->first()->attr('content') : null;
$image = $imageNode->count() ? $imageNode->first()->attr('content') : null;
/**
* parse
*
* Parse the meta data from the given url and populate data member $metaData
*
* @access public
* @return integer
*/
public function parse()
{
// load HTML as DOMDocument object for parsing
$this->html = new DOMDocument;
libxml_use_internal_errors(true);
// Recoding
$source = mb_convert_encoding(file_get_contents($this->url), 'HTML-ENTITIES', 'utf-8');
$this->html->loadHTML($source);
// php built-in get_meta_tags() only read those with name "title", "description" and so on
// so I wrote my own version supporting twitter:title, og:title, etc.
$this->meta = $this->my_get_meta_tags($this->url);
$this->success(); // assume successful
// possible to add more method such as getAuthor()
$this->getTitle();
$this->getDescription();
$this->getImage();
return $this->status;
}
/**
* finalize
*
* Export the meta data parsed
*
* @access public
* @return StdClass
*/
public function finalize()
{
$tmp = new StdClass;
$tmp->url = $this->url;
$tmp->title = $this->metaData->title;
$tmp->description = $this->metaData->description;
$tmp->image = $this->metaData->image;
$tmp->status = $this->status;
return $tmp;
}
/**
* my_get_meta_tags
*
* Require the url to be parsed, read every meta tags found
*
* @access private
* @param string $url
* @return array
*/
private function my_get_meta_tags($url)
{
$metatags = $this->html->getElementsByTagName("meta");
$tmeta = array();
for ($i = 0; $i < $metatags->length; ++$i) {
$item = $metatags->item($i);
$name = $item->getAttribute('name');
if (empty($name)) {
// og meta tags, or twitter meta tags
$tmeta[$item->getAttribute('property')] = $item->getAttribute('content');
} else {
// conventional meta tags
$tmeta[$name] = $item->getAttribute('content');
}
}
return $tmeta;
}
/**
* initizlized
*
* Set the state of the object to be initizlied
*
* @access private
*/
private function initialized()
{
$this->status = self::$STATUS["initialized"];
}
/**
* success
*
* Set the state of the object to be successful
*
* @access private
*/
private function success()
{
$this->status = self::$STATUS["success"];
}
/**
* fail
*
* Set the state of the object to be failed
*
* @access private
*/
private function fail()
{
$this->status = self::$STATUS["fail"];
}
/**
* getTitle
*
* Read meta title based on priorities of the tag name/property,
* fallback to reading <title> and <h1> if meta title not present
*
* @access private
*/
private function getTitle()
{
if (isset($this->meta["og:title"])) {
$this->metaData->title = $this->meta["og:title"];
return;
}
if (isset($this->meta["twitter:title"])) {
$this->metaData->title = $this->meta["twitter:title"];
return;
}
if (isset($this->meta["title"])) {
$this->metaData->title = $this->meta["title"];
return;
}
$title = $this->html->getElementsByTagName("title") or $title = $this->html->getElementsByTagName("h1");
// taking either the title or h1 tag
if (!$title->length) {
// if no h1 tag, nothing good enough to be the site title
$this->fail();
return;
} else {
$this->metaData->title = ($title->length) ? $title->item(0)->nodeValue : "";
}
}
/**
* getDescription
*
* Read meta description based on priorities of the tag name/property.
* No fallback, it doesn't read anything except for the meta tag
*
* @access private
*/
private function getDescription()
{
if (isset($this->meta["og:description"])) {
$this->metaData->description = $this->meta["og:description"];
return;
}
if (isset($this->meta["twitter:description"])) {
$this->metaData->description = $this->meta["twitter:description"];
return;
}
if (isset($this->meta["description"])) {
$this->metaData->description = $this->meta["description"];
return;
}
$this->fail();
return;
}
/**
* getImage
*
* Read meta image url based on priorities of the tag name/property.
* No fallback, it doesn't read anything except for the meta tag
*
* @access private
*/
private function getImage()
{
if (isset($this->meta["og:image"])) {
$this->metaData->image = $this->meta["og:image"];
return;
}
if (isset($this->meta["twitter:image"])) {
$this->metaData->image = $this->meta["twitter:image"];
return;
}
if (isset($this->meta["image"])) {
$this->metaData->image = $this->meta["image"];
return;
}
$this->fail();
}
};
return [
'title' => $title,
'description' => $description,
'image' => $image
];
}
}

View file

@ -38,16 +38,19 @@ class UploadImage
$name = $img['name'];
if ($name) {
self::fileTypeCheck($img['type'], '/');
$filename = $pref . $content_id . '-' . time();
$file = $img['tmp_name'];
$image = new SimpleImage();
$image->load($file);
$image->resizeInCenter(160, 160, "#ffffff");
$image->resizeAllInCenter(160, 160, "#ffffff");
$image->save($path_img . $filename . '.webp', "webp");
$image->resizeInCenter(48, 48, "#ffffff");
$image->resizeAllInCenter(48, 48, "#ffffff");
$image->save($path_img_small . $filename . '.webp', "webp");
$new_img = $filename . '.webp';
@ -63,8 +66,10 @@ class UploadImage
// Delete the old avatar, except for the default one
// Удалим старую аватарку, кроме дефолтной
if ($foto != $default_img && $foto != $new_img) {
@unlink($path_img . $foto);
@unlink($path_img_small . $foto);
if ($foto != false) {
@unlink($path_img . $foto);
@unlink($path_img_small . $foto);
}
}
if ($type == 'facet') {
@ -79,13 +84,15 @@ class UploadImage
return false;
}
public static function postImg($img, $user_id, $type, $content_id)
public static function postImg($img, $type, $content_id)
{
$path_img = HLEB_PUBLIC_DIR . Img::PATH['posts_content'];
$year = date('Y') . '/';
$month = date('n') . '/';
$file = $img['tmp_name'];
$filename = 'post-' . time();
self::fileTypeCheck($img['type'], '/');
// For the body of the post, if png then we will not change the file extension
// Для тела поста, если png то не будем менять расширение файла
@ -111,7 +118,7 @@ class UploadImage
'file_path' => $img_post,
'file_type' => $type ?? 'none',
'file_content_id' => $content_id ?? 0,
'file_user_id' => $user_id,
'file_user_id' => UserData::getUserId(),
'file_is_deleted' => 0
]
);
@ -120,7 +127,7 @@ class UploadImage
}
// Member cover
public static function cover($cover, $content_id, $type)
public static function cover($img, $content_id, $type)
{
switch ($type) {
case 'user':
@ -136,10 +143,12 @@ class UploadImage
$pref = 'cover-';
$default_img = 'cover_art.jpeg';
if ($cover) {
if ($img) {
self::fileTypeCheck($img['type'], '/');
$filename = $pref . $content_id . '-' . time();
$file_cover = $cover['tmp_name'];
$file_cover = $img['tmp_name'];
$image = new SimpleImage();
$image->load($file_cover);
@ -156,13 +165,15 @@ class UploadImage
$cover_art = $user['cover_art'];
} else {
$facet = FacetModel::getFacet($content_id, 'id', $type);
$cover_art = $facet['facet_cover_art'];
$cover_art = $facet['facet_cover_art'] ?? false;
}
// Удалим старую, кроме дефолтной
if ($cover_art != $default_img && $cover_art != $new_cover) {
@unlink($path_cover_img . $cover_art);
@unlink($path_cover_small . $cover_art);
@unlink($path_cover_img . $cover_art);
if ($cover_art != false) {
@unlink($path_cover_small . $cover_art);
}
}
// Запишем обложку
@ -180,17 +191,19 @@ class UploadImage
}
// Post cover
public static function coverPost($cover, $post, $redirect, $user_id)
public static function coverPost($img, $post, $redirect)
{
// Width check
$width_h = getimagesize($cover['tmp_name']);
self::fileTypeCheck($img['type'], $redirect);
$width_h = getimagesize($img['tmp_name']);
if ($width_h < 500) {
is_return(__('msg.five_width'), 'error', $redirect);
}
$path = HLEB_PUBLIC_DIR . Img::PATH['posts_cover'];
$year = date('Y') . '/';
$file = $cover['tmp_name'];
$file = $img['tmp_name'];
$filename = 'c-' . time();
self::createDir($path . $year);
@ -205,16 +218,22 @@ class UploadImage
// Delete if there is an old one
$post_content_img = $post['post_content_img'] ?? false;
if ($post_content_img != $post_img) {
@unlink($path . $post_content_img);
FileModel::removal($post_content_img, $user_id);
if ($post_content_img != false) {
@unlink($path . $post_content_img);
}
FileModel::removal($post_content_img);
}
// Img::PATH['posts_cover'] добавить после запроса.
// UPDATE files SET file_path = CONCAT('/uploads/posts/cover/', file_path) where file_type = 'post';
FileModel::set(
[
'file_path' => $post_img,
'file_type' => 'post',
'file_content_id' => $post['post_id'] ?? 0,
'file_user_id' => $user_id,
'file_user_id' => UserData::getUserId(),
'file_is_deleted' => 0
]
);
@ -223,11 +242,11 @@ class UploadImage
}
// Удаление обложка поста
public static function coverPostRemove($path_img, $user_id)
public static function coverPostRemove($path_img)
{
unlink(HLEB_PUBLIC_DIR . Img::PATH['posts_cover'] . $path_img);
return FileModel::removal($path_img, $user_id);
return FileModel::removal($path_img);
}
// Thumb for post
@ -247,10 +266,14 @@ class UploadImage
copy($image, $local);
}
$image = new SimpleImage();
$image->load($local);
$image->resizeToWidth(1050);
$image->save($path . $year . $filename . '.webp', "webp");
if (!file_exists($local)) {
return false;
}
$img = new SimpleImage();
$img->load($local);
$img->resizeToWidth(1050);
$img->save($path . $year . $filename . '.webp', "webp");
if (file_exists($local)) {
@unlink($local);
@ -268,4 +291,15 @@ class UploadImage
mkdir($path, 0777, true);
}
}
public static function fileTypeCheck($type, $redirect)
{
// permitted
$types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
if (!in_array($type, $types)) {
is_return(__('msg.five_format'), 'error', $redirect);
}
return true;
}
}

View file

@ -248,6 +248,11 @@ class UserData
return self::$myAccount['scroll'] ?? false;
}
static public function getUserNSFW()
{
return self::$myAccount['nsfw'] ?? false;
}
static public function getUserBlog()
{
return MiddlewareModel::getBlog(self::getUserId());

View file

@ -1,240 +0,0 @@
<?php
/**
* Easy enough to use
* hook_action('img');
*
* https://github.com/nahid/hookr
*
* Hook::bindAction('img', function() {
* echo '<img src="/uploads/test.webp">';
* }, 2)
*/
declare(strict_types=1);
namespace App\Hook;
class Hook
{
protected static $hookActions = [];
protected static $hookFilters = [];
protected static $instance = null;
/**
* make singleton
*
* @return static
*/
public static function getInstance()
{
if (is_null(static::$instance)) {
static::$instance = new static();
}
return static::$instance;
}
/**
* declare action hook
*
* @param string $name
* @param array $params
*/
public static function action(string $name, array $params = [])
{
if (isset(static::$hookActions[$name])) {
$actions = static::makePriority($name);
foreach ($actions as $callback) {
static::executeAction($callback['action'], $params);
}
}
}
/**
* bind action with hook
*
* @param string $name
* @param callable $callback
* @param int $priority
*/
public static function bindAction(string $name, callable $callback, int $priority = 0)
{
if (!isset(static::$hookActions[$name])) {
static::$hookActions[$name][] = [
'action' => $callback,
'priority' => $priority,
];
} else {
array_push(static::$hookActions[$name], [
'action' => $callback,
'priority' => $priority,
]);
}
}
/**
* declare filter hook
*
* @param string $name
* @param mixed $data
* @param array $params
* @return mixed
*/
public static function filter(string $name, mixed $data, array $params = [])
{
if (isset(static::$hookFilters[$name])) {
$filters = static::makePriority($name, 'filter');
foreach ($filters as $callback) {
$data = static::executeFilter($callback['action'], $data, $params);
}
}
return $data;
}
/**
* bind filter with hook
*
* @param string $name
* @param callable $callback
* @param int $priority
*/
public static function bindFilter(string $name, $callback, int $priority = 0)
{
if (!isset(static::$hookFilters[$name])) {
static::$hookFilters[$name][] = [
'action' => $callback,
'priority' => $priority,
];
} else {
array_push(static::$hookFilters[$name], [
'action' => $callback,
'priority' => $priority,
]);
}
}
/**
* make class from string with array param
*
* @param string $class
* @param array $params
* @return object
*/
protected static function newClassInstance(string $class, array $params = [])
{
$reflection = new \ReflectionClass($class);
return $reflection->newInstanceArgs($params);
}
/**
* apply action from hook
*
* @param callable $action
* @param array $params
* @return mixed
*/
protected static function executeAction(callable $action, array $params)
{
if (is_callable($action)) {
return call_user_func_array($action, $params);
}
if (is_string($action)) {
$action = explode('@', $action);
$func = static::makeMethodParam($action[1]);
$class = static::makeMethodParam($action[0]);
$instance = static::newClassInstance($class['method'], $class['params']);
if (count($action) > 1) {
return call_user_func_array([$instance, $func['method']], $params);
}
}
}
/**
* @param callable $action
* @param mixed $data
* @param array $params
* @return mixed
*/
protected static function executeFilter(callable $action, mixed $data, array $params = [])
{
if (is_callable($action)) {
array_unshift($params, $data);
return call_user_func_array($action, $params);
}
if (is_string($action)) {
$action = explode('@', $action);
$func = static::makeMethodParam($action[1]);
array_unshift($params, $data);
$class = static::makeMethodParam($action[0]);
$instance = static::newClassInstance($class['method'], $class['params']);
if (count($action) > 1) {
return call_user_func_array([$instance, $func['method']], $params);
}
}
}
/**
* make param from input string
*
* @param string $method
* @return array
*/
protected static function makeMethodParam(string $method)
{
$methods = explode(':', $method);
$param = [];
$method = $methods[0];
if (isset($methods[1])) {
$param = explode(',', $methods[1]);
}
return [
'method' => $method,
'params' => $param,
];
}
/**
* compare two input
*
* @param int $value1
* @param int $value2
* @return int
*/
protected static function compare(int $value1, int $value2)
{
if ($value1['priority'] == $value2['priority']) {
return -1;
}
return ($value1['priority'] < $value2['priority']) ? -1 : 1;
}
/**
* make action/filter priority
*
* @param string $name
* @param string $type
* @return mixed
*/
protected static function makePriority(string $name, string $type = 'action')
{
if ($type == 'action') {
usort(static::$hookActions[$name], [new self, 'compare']);
return static::$hookActions[$name];
}
if ($type == 'filter') {
usort(static::$hookFilters[$name], [new self, 'compare']);
return static::$hookFilters[$name];
}
}
}

View file

@ -14,4 +14,3 @@ return [
'to_main' => 'الى الصفحة الرئيسية',
'error_404' => 'خطأ 404',
];

View file

@ -18,6 +18,8 @@ return [
'advertising' => 'أعلانات',
'catalog' => 'فهرس',
'facets' => 'جوانب',
'profile' => 'حساب تعريفي',
'poll' => 'استطلاع',
'users' => 'الاعضاء',
'time' => 'الوقت',
'avatar' => 'الصورة الرمزية',
@ -51,7 +53,7 @@ return [
'remove' => 'حذف',
'completed' => 'تم اتمام الامر',
'reward_user' => 'كافئ المشارك',
'topic' => 'موضوع',
'topics' => 'مواضيع',
'blog' => 'مدونة',
@ -70,7 +72,7 @@ return [
'item' => 'موقع',
'invite' => 'ادعو',
'report' => 'شكوى',
'submenu' => 'قائمة فرعية',
'update' => 'تحديث',
'ban' => 'حظر',
@ -86,6 +88,7 @@ return [
'contacts' => 'جهات الاتصال',
'tools' => 'الاداوات',
'trust_level' => 'مستوى الثقة',
'number_comments' => 'عدد التعليقات',
'logs' => 'السجلات',
'reports' => 'علم (شكوات)',
'approve' => 'موافقة',
@ -112,7 +115,7 @@ return [
'tl4_title' => 'متردد',
'tl5_title' => 'قائد',
'tl10_title' => 'طاقم',
'deleted' => 'تمت ازالته',
'added' => 'تمت اضافته',
'restored' => 'تم استرجاعه',
@ -122,17 +125,17 @@ return [
'settings' => 'إعدادات',
'interface' => 'واجهه المستخدم',
'functions' => 'المهام',
'url_help' => 'URL الموقع (مع https)',
'email_help' => 'البريد الإلكتروني العام للتواصل',
'name_help' => 'الاسم المختصر للموقع',
'title_help' => 'اسم الموقع الكامل',
'img_path' => 'المسار إلى الصورة (مقدمة عن الموقع)',
'img_path_help' => 'مستخدم في og: صورة وأماكن أخرى عندما لا يكون هناك مقدمة في المنشور ، على سبيل المثال',
'img_path_web' => 'مسار الصورة (مقدمة عن الكتالوج)',
'img_path_web_help' => 'تستخدم في og: صورة لدليل الموقع',
'banner_title' => 'رأس البانر',
'banner_title_help' => 'عنوان البانر على الصفحة الرئيسية للموقع ، إذا لم يكن المشارك مخولاً',
'banner_desc' => 'نص البنر',
@ -148,7 +151,7 @@ return [
'count_like_feed_help' => 'كم عدد الإعجابات التي يجب أن تظهر على المنشور في الصفحة المركزية للموقع',
'type_post_feed' => 'ظهور المنشور في الخلاصة',
'type_post_feed_help' => 'الكلاسيكية أو البطاقة. إذا كان كلاسيكيًا ، فهذا تصميم بسيط',
'ads_home_post' => 'الصفحة الرئيسية, التدفق, بعد 4 منشورات',
'ads_home_sidebar' => 'الصفحة الرئيسية, الشريط الجانبي',
'ads_home_menu' => 'الصفحة الرئيسية, اسفل القائمة اليسرى',

View file

@ -12,13 +12,17 @@ return [
'home' => 'الرئيسية',
'catalog' => 'التصنيف',
'feed' => 'التدفق',
'minimum' => 'الحد الأدنى',
'poll' => 'تصويت',
'polls' => 'استطلاعات الرأي',
'closed' => 'مغلق',
'hi' => 'مرحباً',
'news' => 'الاخبار',
'team' => 'الفريق',
'teams' => 'الفرق',
'subsections' => 'الأقسام الفرعية',
'table' => 'الطاولة',
'team_not_users' => 'لا يوجد أعضاء في الفريق بعد...',
'total_votes' => 'مجموع الأصوات',
'owner' => 'مالك',
'top' => 'الافضل',
'admin' => 'لوحة المدير',
@ -85,7 +89,7 @@ return [
'write_message' => 'لكتابة الرسالة',
'send' => 'ارسال',
'information' => 'معلومات',
'donate' => 'ادعم هذا المشروع',
'donate' => 'ادعم هذا المشروع',
'review' => 'مراجعة',
'contacts' => 'جهات الاتصال',
'public_data' => 'البيانات العامة مرئية في الملف الشخصي.',
@ -99,8 +103,9 @@ return [
'nickname' => 'اسم مستعار',
'name' => 'اسم',
'password' => 'كلمة السر',
'new_password' => 'كلمة سر جديدة',
'repeat' => 'اعادة',
'new_password' => 'كلمة السر الجديدة',
'old_password' => 'كلمة السر الحالية',
'confirm_password' => 'تأكيد كلمة السر الجديدة',
'show' => 'اظهار',
'new' => 'جديد',
'new_ones' => 'جديدة',
@ -162,7 +167,17 @@ return [
'drafts' => 'مسودات',
'cancel' => 'الغاء',
'reply' => 'رد',
'is_nsfw' => 'قم بتمكين عرض محتوى البالغين و NSFW (+ تمويه الصور المصغرة) في الخلاصة.',
'nsfw_post' => 'هل محتوى الكبار (NSFW)?',
'hidden_post' => 'الوصول عبر الرابط؟',
'hidden_post_help' => 'يمكن فقط للمستخدمين الذين لديهم الرابط رؤيته.',
'delete_profile' => 'حذف الملف الشخصي',
'read_carefully' => 'اقرأ بعناية ، مهم جداً!',
'read_information' => 'أنت على وشك حذف الملف الشخصي الخاص بك. لحذف ملف الشخصي ، يجب عليك تأكيد استعدادك لحذف كافة المعلومات المدرجة. يعد حذف ملف الشخصي <strong> إجراء لا رجوع فيه </strong> ، فلن تتمكن من استعادة بياناتك المفقودة.',
// Editor
'foto' => 'صورة',
'bold' => 'عريض',
@ -180,7 +195,9 @@ return [
'attach_files' => 'يمكن لصق الملفات من المحفظة.',
'entry_policy' => 'وافق على الاعضاء الجدد',
'option' => 'تحرير الاستطلاع',
'back' => 'عودة',
'edit' => 'تعديل',
'save' => 'حفظ',
@ -189,13 +206,15 @@ return [
'add_topic' => 'اضافة موضوع',
'add_blog' => 'اضافة مدونة',
'add_category' => 'اضافة الفئة',
'add_poll' => 'إضافة استطلاع',
'edit_poll' => 'تحرير الاستطلاع',
'edit_category' => 'تعديل الفئة',
'edit_post' => 'تعديل المنشور',
'edit_topic' => 'تعديل الموضوع',
'edit_blog' => 'تعديل المدونة',
'edit_page' => 'تعديل الصفحة',
'edit_section' => 'تعديل القسم',
'share_post' => 'آخر حصة',
'share_topic' => 'موضوع المشاركة',
'share_blog' => 'مشاركة المدونة',
@ -214,7 +233,7 @@ return [
'no_cover' => 'لايوجد غلاف بعد...',
'no_invites' => 'انت لم تنشئ اي دعوات',
'no_content' => 'للاسف, لايوجد محتوى بعد',
'no_dialogs' => 'للاسف, لا يوجد حوارات بعد',
'no_dialogs' => 'للاسف, لا يوجد حوارات بعد',
'no_posts' => 'للاسف, لايوجد منشورات بعد',
'no_favorites' => 'للاسف, لا يوجد مفضلات بعد',
'no_comments' => 'للاسف, لايوجد تعلقيات بعد',
@ -223,16 +242,17 @@ return [
'default' => 'افتراضي',
'qa' => 'الاسئلة و الاجوبة',
'best_answer' => 'أفضل إجابة',
'raise_answer' => 'رفع الجواب',
'answered' => 'تمت الاجابة عليه',
'post_translation' => 'المنشور عبارة عن ترجمة ؟',
'translation' => 'الترجمة',
'format_Q&A' => 'هذا سؤال (يتم نشره بصيغة سؤال) ؟',
'poll_closed' => 'هل هذا الاستطلاع مغلق؟',
'pin' => 'ثبت هذا المنشور ؟',
'source' => 'المصدر',
'website' => 'الموقع الالكتروني',
'websites' => 'المواقع',
'sites' => 'المواقع',
'related' => 'ذات صلة',
'related_posts' => 'منشورات ذات صلة',
'parents' => 'الرئيسيات',
@ -281,7 +301,7 @@ return [
'forgot_password' => 'نسيت كلمة السر',
'rules' => 'قوانين الموقع',
'restriction' => 'القيود',
'text_closed' => 'لا يمكن عرض هذا النص المخفي دون تصريح',
/* Date and time + events */
@ -291,6 +311,7 @@ return [
'num_message' => ['رسالة', 'رسائل', 'رسائل'],
'num_answer' => ['اجابة', 'اجابات', 'اجابات'],
'num_comment' => ['تعليق', 'تعليقات', 'تعليقات'],
'num_post' => ['منشور', 'منشورات', 'منشورات'],
'num_view' => ['مشاهدة', 'مشاهدات', 'مشاهدات'],
'num_up' => ['اعجابات', 'اعجابات', 'اعجابات'],
@ -305,16 +326,6 @@ return [
'posts' => 'منشورات',
'language' => 'اللغة',
'ru_language' => 'Русский',
'ua_language' => 'Український',
'en_language' => 'English',
'de_language' => 'Deutsch',
'sk_language' => 'Slovenský',
'fr_language' => 'Français',
'zh_CN_language' => '简体中文',
'zh_TW_language' => '繁体中文',
'ro_language' => 'România',
'ar_language' => 'العربية',
'type' => 'نوع',
'logo' => 'شعار',
@ -341,19 +352,19 @@ return [
'pages' => 'صفحات',
'go_to' => 'ذهاب',
'seo' => 'SEO',
'url' => 'الرابط',
'url' => 'رابط',
'url_parsing' => 'رابط المقالة (للجلب)',
'slug' => 'اختصار',
'email' => 'بريد الكتروني',
'wiki' => 'ويكي',
'edit_answer' => 'لـ\'تعديل الاجابة',
'edit_comment' => 'دعونا نغير التعليق',
'enter' => 'ادخل',
'enter_password' => 'ادخل كلمة السر',
'rec_posts' => 'مواضيع موصى بها',
'topic_subs' => 'اشترك بالمواضيع و اقرئهم في التدفق',
'i_read' => 'مقروء',
'message_PM' => 'عند استلام الرسالة',
'appeal_@' => 'حين يتم الاشارة بواسطة @',
@ -377,15 +388,25 @@ return [
'invite_features' => 'يمكنك دعوة الاصدقاء',
'content_deleted' => '{name} محذوف',
'topic_deleted' => 'تم حذف الموضوع',
'facet_comments_disabled' => 'هل تريد تعطيل التعليقات؟',
'topic_comments_disabled' => 'التعليقات معطلة في الموضوع.',
'blog_comments_disabled' => 'قام مؤلف المدونة بتعطيل التعليقات.',
'dir_comments_disabled' => 'التعليقات معطلة في هذا القسم.',
'endless_scroll' => 'تفعيل التمرير الى لا نهاية؟',
'notification_email' => 'تنبيه بواسطة البريد الالكتروني',
'notifications_limit' => 'اظهار 100 اشعار على الاقل',
'ignored' => 'تم تجاهلهم',
'ignore' => 'يتجاهل',
'ignored' => 'تم تجاهلهم',
'ignored_users' => 'مستخدمين تم تجاهلهم',
'ignored_users_help' => '.الاعضاء الذين يقومون بالنشر لن يتم مشاهدة منشوراتهم في التدفق',
'ignored_no' => 'ليس هناك اي اعضاء تم تجاهلهم.',
'ignored_no' => 'ليس هناك اي اعضاء تم تجاهلهم.',
'not_confirmed' => 'غير مؤكد.',
'resend_email' => 'تحقق من صندوق بريدك الإلكتروني أو أعد إرسال بريد إلكتروني جديد.',
/* Notifications and logs */
'notif_add_pm' => 'ارسل لك {url}رسالة خاصة{a}',

View file

@ -10,7 +10,7 @@ return [
'mail_confirm' => 'بعد تقديم النموذج المكتمل ، سيُطلب منك التحقق من عنوان بريدك الإلكتروني. من المهم ملاحظة أنك لن تتمكن من متابعة بقية عملية الإعداد حتى تنتهي من ذلك.',
'login_info' => 'يمنحك التسجيل القدرة على نشر المنشورات والرد والتعليق والتصويت.',
'invate_text' => 'لست مستخدم حتى الآن؟ يتم التسجيل عن طريق الدعوة فقط لمكافحة البريد العشوائي وزيادة المساءلة. إذا كنت تعرف <a href="/users"> المستخدم الحالي </a> للموقع ، فاطلب منه دعوة.',
// form validation on registration page
'nickname_empty' => 'لا يمكن أن يكون الاسم المستعار فارغًا.',
'nickname_least' => 'يجب أن يكون الاسم المستعار> = {info} حرفًا.',
@ -21,4 +21,3 @@ return [
'password_again' => 'أدخل كلمة المرور مرة أخرى.',
'password_mismatch' => 'كلمة المرور غير متطابقة.',
];

View file

@ -30,7 +30,10 @@ return [
'edit_topic' => 'تستخدم المواضيع لتجميع (التنقل) المشاركات. هذا التنقل ، خذها على محمل الجد.',
'edit_blog' => 'عادة ما يتم إنشاء المدونات من قبل المساهمين. المدونة مخصصة لمستخدم معين.',
'edit_section' => 'هذا هو تحرير التنقل لصفحات الخدمة (التوثيق). خذها على محمل الجد.',
'team_info' => 'المستخدمين الاخرين ايضاً يمكنهم نشر مقالات في مدونتك - لهذا تحتاج لمنحهم حق الوصول.',
'draft_info' => 'يمكن للمؤلف فقط قراءة المسودات.',
'add_poll' => 'املأ جميع الحقول. يمكن استخدام هذا الاستطلاع في أجزاء أخرى من الموقع (على سبيل المثال ، في المنشورات).',
'poll_info' => 'تصويتي مرتبة حسب الوقت.',
];

View file

@ -8,19 +8,22 @@
return [
'appealed_subject' => '{name} اتصل بك (@)',
'appealed_message' => '<p>تم الاتصال بك (@). انظر:<p><p>{url}/p>',
'appealed_message' => '<p>تم الاتصال بك (@). انظر:<p><p>{url}</p>',
'changing_password_subject' => '{name} — استعادة كلمة السر',
'changing_password_message' => '<p>رابط اعادة تعين كلمة السر الخاصة بك:</p><p>{url}</p>',
'test_subject' => '{name} — اختبار البريد (لوحة المدير)',
'test_message' => '<p>هذا البريد الإلكتروني هو بريد إلكتروني تجريبي تم إرساله من خلال لوحة الإدارة.</p>',
'activate_email_subject' => '{name} — تفعيل البريد',
'activate_email_message' => '<p>لمتابعة التسجيل ، قم بتفعيل بريدك الإلكتروني. اتبع هذا الرابط:</p><p>{url}</p>',
'new_email_subject' => '{name} — تغيير الايميل',
'new_email_message' => '<p>للمتابعة ، قم بتفعيل بريدك الإلكتروني بالضغط على الرابط:</p><p>{url}</p>',
'invite_reg_subject' => '{name} — دعوة للانظمام (ادعو)',
'invite_reg_message' => '<p>لقد تمت دعوتك للانضمام إلى المجتمع. إذا وافقت. ثم اتبع الرابط:</p><p>{url}</p>',
'footer' => '<p>تم إنشاء هذا البريد الإلكتروني تلقائيًا. <br> لست بحاجة إلى الرد عليه. </ p> <p> الإدارة.<br>{name}</p>',
];

View file

@ -8,14 +8,14 @@
return [
// Member profile
// Профиль участника
// Member profile
// Профиль участника
'profile_title' => '{name} — ملف العضو ',
'profile_desc' => '{name} — صفحة ملف العضو. المنشورات, الجوائز و جهات الاتصالات. {information}',
'profile_posts_title' => '{name} — قائمة المنشورات ',
'profile_posts_all_desc' => '{name} — قائمة المنشورات, مقالات المشارك بترتيب زمني. جميع المنشورات على الموقع.',
'profile_comments_title' => '{name} — تعليقات المشارك \المشاركين',
'profile_comments_desc' => '{name} — تعليقات المشارك \ المشاركين بالترتيب الزمني. {information}',
// end
@ -23,31 +23,31 @@ return [
'all_users' => 'قائمة المشاركين',
'all_users_info' => 'قائمة المشاركين بحسب ترتيب نشاطهم على الموقع',
'all_users_desc' => 'ترتيب الأعضاء حسب نشاطهم على الموقع. القدرة على عرض معلومات الملف الشخصي',
'new_users' => 'الاعضاء الجدد',
'new_users_info' => 'قائمة الأعضاء الذين قاموا بالتسجيل في الموقع مؤخرًا',
'new_users_desc' => 'الأعضاء الذين سجلوا في الموقع مؤخرًا. عرض النشاط ، الصور الرمزية ، الملف الشخصي',
'all_blogs' => 'كل المدونات',
'all_blogs_info' => 'المدونات التي تم انشائها بواسطة الاعضاء',
'all_blogs_desc' => 'المدونات بترتيب تسجيلها في الموقع ، والقدرة على عرض المدونات التي تم إنشاؤها ، والاشتراك فيها ، وعرض الإحصائيات',
'new_blogs' => 'المدونات الجديدة',
'new_blogs_info' => 'المدونات التي تمت اضافتها على الموقع مؤخراً',
'new_blogs_desc' => 'المدونات التي تمت اضافتها على الموقع مؤخرًا. المدونات الشخصية للمشاركين ، إمكانية الاشتراك في مدونات شيقة',
'new_blogs_desc' => 'المدونات التي تمت اضافتها على الموقع مؤخرًا. المدونات الشخصية للمشاركين ، إمكانية الاشتراك في مدونات شيقة',
'my_blogs' => 'مدوناتي',
'my_blogs_info' => 'المدونات التي أتابعها أو أنشئها',
'my_blogs_desc' => 'المدونات التي قرأتها أو أنشأتها',
'all_topics' => 'كل المواضيع',
'all_topics_info' => 'جميع الموضوعات الموجودة على الموقع حسب شعبيتها',
'all_topics_desc' => 'صفحة مواضيع مرتبة حسب الشعبية. حسب عدد المنشورات المنشورة ، القدرة على الاشتراك في المدونات',
'new_topics' => 'مواضيع جديدة',
'new_topics' => 'مواضيع جديدة',
'new_topics_info' => 'مواضيع جديدة, مواضيع تمت اضافتها مؤخراً',
'new_topics_desc' => 'مواضيع جديدة أضيفت إلى الموقع مؤخرًا. إحصائيات الموضوعات والقدرة على الاشتراك في الموضوعات',
'my_topics' => 'اَقرءها',
'my_topics_info' => 'المواضيع التي اشترك بها',
'my_topics_desc' => 'المواضيع التي اَقرءها او قمت بأنشائها',
@ -56,11 +56,11 @@ return [
'comments_deleted_info' => 'ازالة التعلقيات...',
'answers_all_info' => 'كل الاجابات...',
'answers_deleted_info' => 'الردود المحذوفة...',
'comments_desc' => 'كل التعليقات (لكل ردود) مرتبة حسب الأولوية في المجتمع',
'domain_desc' => 'تجميع المشاركات في المجتمع حسب النطاق',
'all_comments' => 'كل التعليقات',
'feed_facet_desc' => 'التدفق العام ',
'feed_facet_posts_desc' => 'تدفق النشور',
'feed_facet_questions_desc' => 'موضوع الأسئلة. ',

View file

@ -47,24 +47,29 @@ return [
'code_incorrect' => 'الكود غير صحيح او تم استخدامه مسبقاً',
'yes_email_pass' => 'الان يمكنك استخدام بريدك الالكتروني و كلمةالسر.',
'email_replay' => 'البريد الالكتروني هذا مستخدم بالفعل في هذا الموقع.',
'email_forbidden' => 'التسجيل مع البريد الإلكتروني المحدد ممنوع',
'multiple_accounts' => 'لا تقم بتسجيل عدة حسابات',
'five_width' => 'عرض الغلاف اقل 500px',
'five_format' => 'نوع الملف خاطئ',
'silent_mode' => 'لا يمكنك نشر محتوىt, سيتم مراجعة حسابك',
'nick_character' => 'هناك الكثير من الحروف المكررة في الاسم المستعار',
'nick_exist' => 'هذا الاسم المستعار موجود بالفعل',
'check_your_email' => 'افحص بريدك الالكتروني لتفعيل حسابك',
'new_email' => 'تحقق من بريدك الإلكتروني لتفعيل البريد الإلكتروني',
'user_already' => 'هذا المستخدم مسجل بالفعل في هذا الموقع',
'invate_replay' => 'انت ارسلت دعوة لهذا المستقبل بالفعل',
'invate_limit_stop' => 'لقد تجاوزت الحد المسموح لارسال الدعوات',
'invite_created' => 'تم انشاء الدعوة',
'url_reserved' => 'عنوان نطاق المدونة مستخدم',
'url_correctness' => 'عنوان النطاق غير صحيح',
'string_length' => 'خطأ في الطول {name}',
'slug_correctness' => '{name} يجب ان يحتوي فقط على احرف لاتينية, ارقام',
'email_correctness' => 'بريد غير صالح',
'limit_day' => 'لقد تجاوزت الحد المسموح لليوم',
'content_audit' => 'تم ارسال رسالتك للمراجعة',
'access_denied' => 'تم رفض الوصول الخاص بك',
'field_limit' => 'بلغ عدد الحقول الحد الأقصى.',
];

View file

@ -18,4 +18,5 @@ return [
'sign_in' => 'تسجيل الدخول',
'enter_password' => 'ادخل كلمة السر',
'under_reconstruction' => 'الموقع تحت الصيانة, الدخول مسموح للطاقم فقط.',
'under_maintenance' => 'نمط الصيانة.',
];

View file

@ -10,7 +10,7 @@ return [
'all' => 'الكل',
'posts' => 'المنشورات',
'websites' => 'المواقع',
'answers' => 'اجابات',
'comments' => 'تعليقات',
'registration' => 'التسجيل',
'sign_in' => 'تسجيل الدخول',
'find' => 'البحث...',
@ -25,4 +25,3 @@ return [
'help' => 'بحث الموقع والمزيد...',
'query' => 'طلب',
];

View file

@ -14,6 +14,7 @@ return [
'soft' => 'لين',
'website' => 'موقع الكتروني',
'websites' => 'مواقع',
'comments' => 'تعليقات',
'on_website' => 'الى الموقع الالكتروني',
'deleted' => 'بعيد',
'facets' => 'جوانب',
@ -28,7 +29,8 @@ return [
'deny_replies' => 'رفض الردود؟',
'posted' => 'منشور؟',
'necessarily' => 'مطلوب ملئه',
'status' => 'حالة الرابط',
'status' => 'حالة',
'refresh' => 'ينعش',
'there_program' => 'هل هناك برنامج؟',
'there_forum' => 'هل لهذا الموقع منتدى؟',
'there_portal' => 'هذه بوابة؟',
@ -40,6 +42,7 @@ return [
'related_posts' => 'منشورات ذو صلة',
'desc_formed' => 'تم انشاء الوصف',
'by_date' => 'بحسب التاريخ',
'top' => 'الافضل',
'top_view' => 'بحسب التقيم',
'new_sites' => 'مواقع جديدة',
'audits_view' => 'يتطلب اخذ بعين الاعتبار',
@ -68,11 +71,11 @@ return [
'closed' => 'مناقشة الموقع محظور. المؤلف أو فريق العمل قاموا بغلق النقاش.',
'screenshot_time' => 'اخذ لقطة شاشة قد يستغرق بعض الوقت.',
'audits_home_title' => 'تقارير الموقع',
'audits_home_desc' => 'المواقع تحت المراجعة',
'num_website' => ['موقع', 'مواقع', 'مواقع'],
'news' => 'الاخبار و الاعلام',
'internet' => 'الانترنيت',
'culture' => 'ثقافة و فن',
@ -97,22 +100,21 @@ return [
'website_correctness' => 'العنون (الرابط) لهذا الموقع غير صحيح',
'site_replay' => 'موقع مماثل موجود بالفعل',
'data_help' => '<i class="gray-600">صيغة العنوان:</i><br> «LibArea» — community<br><br><i class="gray-600">الوصف (بدون اعلانات)):</i><br> ...ماذا يوجد بالموقع؟<i>',
'data_help' => '<i class="gray-600">صيغة العنوان:</i><br> «LibArea» — community<br><br><i class="gray-600">الوصف (بدون اعلانات)):</i><br> ...ماذا يوجد بالموقع؟',
'admin_help' => 'قسم مغلق متاح فقط للموظفين',
'add_category' => 'اضافة تصنيف',
'add_website' => 'اضافة موقع',
'edit_website' => 'تعديل موقع',
'sidebar_info' => 'تصنيفات المواقع منظمة بحسب العناوين النمطية',
'banner_info' => 'تصنيفات المواقع مع التعليقات التوضيحية ولقطات الشاشة. <br> اعادة صياغة الأوجه ، البحث. الإشارات المرجعية على الموارد مع القدرة على التصويت للمواقع والبرامج والتصنيف',
'main_title' => 'قاموس الموقع',
'main_desc' => 'قائمة المواقع في الدليل مرتبة ترتيبًا زمنيًا. القدرة على البحث ، المرجعية ، الفرز حسب الشعبية',
'deleted_title' => 'مواقع بعيدة',
'deleted_desc' => '...',
'audits_title' => 'مراجعة الموقع',
'audits_desc' => '...',
'all' => 'الكل',
'github' => 'غيت هاب',

View file

@ -14,4 +14,3 @@ return [
'to_main' => 'To home',
'error_404' => 'Error 404',
];

View file

@ -18,6 +18,8 @@ return [
'advertising' => 'Advertising',
'catalog' => 'Catalog',
'facets' => 'Facets',
'profile' => 'Profile',
'poll' => 'Poll',
'users' => 'Members',
'time' => 'Time',
'avatar' => 'Avatar',
@ -51,7 +53,7 @@ return [
'remove' => 'Delete',
'completed' => 'Command completed',
'reward_user' => 'Reward the participant',
'topic' => 'Topic',
'topics' => 'Topics',
'blog' => 'Blog',
@ -70,7 +72,7 @@ return [
'item' => 'Website',
'invite' => 'Invite',
'report' => 'A complaint',
'submenu' => 'Submenu',
'update' => 'Update',
'ban' => 'Ban',
@ -86,6 +88,7 @@ return [
'contacts' => 'Contacts',
'tools' => 'Tools',
'trust_level' => 'Trust level',
'number_comments' => 'Number of comments',
'logs' => 'Logs',
'reports' => 'Flags (complaints)',
'approve' => 'Approve',
@ -112,27 +115,27 @@ return [
'tl4_title' => 'Frequenter',
'tl5_title' => 'Leader',
'tl10_title' => 'Staff',
'deleted' => 'Removed',
'added' => 'Added',
'restored' => 'Restored',
// Settings section
// Раздел настройки
'settings' => 'Settings',
'interface' => 'Interface',
'functions' => 'Functions',
'url_help' => 'Site URL (with https)',
'email_help' => 'Public email for communication',
'name_help' => 'Site short name',
'title_help' => 'Full site name',
'img_path' => 'The path to the photo (intro for the site)',
'img_path_help' => 'Used in og:image and other places when there is no intro in the post, e.g.',
'img_path_web' => 'Path to photo (intro for catalog)',
'img_path_web_help' => 'Used in og:image for site directory',
'banner_title' => 'Banner header',
'banner_title_help' => 'Banner title on the main page of the site, if the participant is not authorized',
'banner_desc' => 'Banner Body',
@ -148,7 +151,7 @@ return [
'count_like_feed_help' => 'How many likes should a post get to be visible on the central page of the site',
'type_post_feed' => 'Appearance of the post in the feed',
'type_post_feed_help' => 'Classic or Card. If Classic, then this is a minimal design',
'ads_home_post' => 'Home page, feed, after 4 posts',
'ads_home_sidebar' => 'Home page, sidebar',
'ads_home_menu' => 'Home page, under the left menu',
@ -157,5 +160,5 @@ return [
'ads_post_answer' => 'Full post, after 2 replies',
'ads_catalog_home' => 'Main page of the catalog, under the banner',
'ads_catalog_sidebar' => 'Catalog sidebar',
];

View file

@ -12,13 +12,18 @@ return [
'home' => 'Home',
'catalog' => 'Catalog',
'feed' => 'Feed',
'poll' => 'Poll',
'polls' => 'Polls',
'minimum' => 'Minimum',
'closed' => 'Сlosed',
'hi' => 'Hey',
'news' => 'News',
'team' => 'Team',
'teams' => 'Teams',
'subsections' => 'Subsections',
'table' => 'Table',
'team_not_users' => 'There is no member in the team yet...',
'total_votes' => 'Total Votes',
'owner' => 'Owner',
'top' => 'TOP',
'one_month' => 'month',
@ -88,7 +93,7 @@ return [
'write_message' => 'To write a message',
'send' => 'Send',
'information' => 'Information',
'donate' => 'Support the project',
'donate' => 'Support the project',
'review' => 'Review',
'contacts' => 'Contacts',
'public_data' => 'Public data visible in the profile.',
@ -100,10 +105,11 @@ return [
'reset' => 'Reset',
'invited_guests' => 'Invited',
'nickname' => 'Nickname',
'name' => 'Имя',
'name' => 'Name',
'password' => 'Password',
'new_password' => 'New Password',
'repeat' => 'Repeat',
'old_password' => 'Old Password',
'confirm_password' => 'Repeat Password',
'show' => 'Show',
'new' => 'New',
'new_ones' => 'New',
@ -165,7 +171,17 @@ return [
'drafts' => 'Drafts',
'cancel' => 'Cancel',
'reply' => 'Reply',
'is_nsfw' => 'Enable viewing adult content and NSFW (+blur thumbnails) in the feed.',
'nsfw_post' => 'Is the content adult (NSFW)?',
'hidden_post' => 'Access via link?',
'hidden_post_help' => 'Only users with link can see it.',
'delete_profile' => 'Delete profile',
'read_carefully' => 'Read carefully, it\'s really important!',
'read_information' => 'You are about to delete your profile. To delete a profile, you must confirm that you are ready to delete all of the information listed. Deleting a profile is a <strong>irreversible action</strong>, you won\'t be able to get your lost data back.',
// Editor
'foto' => 'Foto',
'bold' => 'Bold',
@ -183,20 +199,24 @@ return [
'attach_files' => 'Files can be pasted from clipboard.',
'entry_policy' => 'Approve new members',
'option' => 'Option',
'back' => 'Back',
'edit' => 'Change',
'save' => 'Save',
'add' => 'Add',
'add_post' => 'Add post',
'add_post' => 'Add Post',
'add_topic' => 'Add Topic',
'add_blog' => 'Add blog',
'add_category' => 'Add category',
'edit_category' => 'Change category',
'edit_post' => 'Edit post',
'add_category' => 'Add Category',
'add_poll' => 'Add Poll',
'edit_poll' => 'Edit Poll',
'edit_category' => 'Change Category',
'edit_post' => 'Edit Post',
'edit_topic' => 'Edit Topic',
'edit_blog' => 'Edit blog',
'edit_page' => 'Edit page',
'edit_blog' => 'Edit Blog',
'edit_page' => 'Edit Page',
'edit_section' => 'Edit Section',
'share_post' => 'Share Post',
@ -217,25 +237,26 @@ return [
'no_cover' => 'No covers yet',
'no_invites' => 'You have not created invitations',
'no_content' => 'Sorry, no content yet',
'no_dialogs' => 'Sorry, there are no dialogues yet',
'no_dialogs' => 'Sorry, there are no dialogues yet',
'no_posts' => 'Sorry, no posts yet',
'no_favorites' => 'Sorry, there are no bookmarks yet',
'no_comments' => 'Unfortunately, there are no comments yet',
'no_answers' => 'Sorry, no answers yet',
'choose_dialogue' => 'Select a dialogue to view',
'default' => 'Default',
'default' => '(default)',
'qa' => 'Questions and answers',
'best_answer' => 'Best Answer',
'raise_answer' => 'Raise answer',
'answered' => 'Answered',
'post_translation' => 'Post is translations ?',
'translation' => 'Translation',
'format_Q&A' => 'This is a question (will become a Q&A format) ?',
'poll_closed' => 'Is this poll closed?',
'pin' => 'Pin this post ?',
'source' => 'Source',
'website' => 'Website',
'websites' => 'Sites',
'sites' => 'Sites',
'related' => 'Related',
'related_posts' => 'Related posts',
'parents' => 'Parents',
@ -284,7 +305,7 @@ return [
'forgot_password' => 'Forgot your password',
'rules' => 'Site rules',
'restriction' => 'Restrictions',
'text_closed' => 'Without authorization it is forbidden to view this hidden text',
/* Date and time + events */
@ -294,6 +315,7 @@ return [
'num_message' => ['Message', 'Messages', 'Messages'],
'num_answer' => ['Answer', 'Answers', 'Answers'],
'num_comment' => ['Comment', 'Comments', 'Comments'],
'num_post' => ['Post', 'Posts', 'Posts'],
'num_view' => ['View', 'Views', 'Views'],
'num_up' => ['likes', 'likes', 'likes'],
@ -308,16 +330,6 @@ return [
'posts' => 'Posts',
'language' => 'Localization',
'ru_language' => 'Русский',
'ua_language' => 'Український',
'en_language' => 'English',
'de_language' => 'Deutsch',
'sk_language' => 'Slovenský',
'fr_language' => 'Français',
'zh_CN_language' => '简体中文',
'zh_TW_language' => '繁体中文',
'ro_language' => 'România',
'ar_language' => 'العربية',
'type' => 'Type',
'logo' => 'logo',
@ -349,14 +361,14 @@ return [
'slug' => 'SLUG',
'email' => 'Email',
'wiki' => 'Wiki',
'edit_answer' => 'Let\'s change the answer',
'edit_comment' => 'Change the comment',
'enter' => 'Enter',
'enter_password' => 'Enter password',
'rec_posts' => 'recommended posts',
'topic_subs' => 'Subscribe to topics and read them in the feed',
'i_read' => 'I read',
'message_PM' => 'When the PM message came',
'appeal_@' => 'When contacted via @',
@ -379,22 +391,32 @@ return [
'invited_you' => 'You were invited by a member from this site. Enter invite',
'invite_features' => 'You can invite friends',
'content_deleted' => '{name} deleted',
'content_deleted' => '{name} deleted',
'topic_deleted' => 'The topic has been deleted',
'facet_comments_disabled' => 'Disable comments?',
'topic_comments_disabled' => 'Comments are disabled in the Topic.',
'blog_comments_disabled' => 'The Blog author has disabled comments.',
'dir_comments_disabled' => 'Comments are disabled in this Section.',
'endless_scroll' => 'Enable infinite scroll?',
'notification_email' => 'Notify by email',
'notifications_limit' => 'Showing last 100 notifications',
'ignored' => 'Ignored',
'ignore' => 'Ignore',
'ignored' => 'Ignored',
'ignored_users' => 'Ignored users',
'ignored_users_help' => 'Users whose posts you will not see in the feed.',
'ignored_no' => 'You don\'t have users that you ignore.',
'ignored_no' => 'You don\'t have users that you ignore.',
'not_confirmed' => 'not confirmed.',
'resend_email' => 'Check your email inbox or resend a new email.',
/* Notifications and logs */
'notif_add_pm' => 'wrote to you {url}private message{a}',
'notif_add_comment' => 'commented {url}your answer{a}',
'notif_add_comment_comment' => 'replied to {url}your comment{a}',
'notif_add_answer' => 'replied to {url}your post{a}',
'notif_add_answer' => 'replied to {url}post{a}',
'notif_add_flag' => 'enrolled {url}a complaint{a}',
'notif_add_audit' => 'required {url}content audit{a}',
'notif_references_post' => 'mentioned you in {url}post{a}',

View file

@ -10,7 +10,7 @@ return [
'mail_confirm' => 'After submitting the completed form, you will be asked to verify your email address. It is important to note that you will not be able to proceed through the rest of the onboarding process until you have done so.',
'login_info' => 'Authorization gives you the ability to publish posts, reply, comment and vote.',
'invate_text' => 'Not a user yet? Registration is by invitation only to fight spam and increase accountability. If you know the <a href="/users">current user</a> of the site, ask them for an invite.',
// form validation on registration page
'nickname_empty' => 'Nickname cannot be empty.',
'nickname_least' => 'Nickname must be >= {info} characters.',
@ -21,4 +21,3 @@ return [
'password_again' => 'Enter the password again.',
'password_mismatch' => 'Password mismatch.',
];

View file

@ -33,4 +33,7 @@ return [
'team_info' => 'Other participants can also post articles to your Blog — for this you need to grant them access.',
'draft_info' => 'Only the author can read drafts.',
'add_poll' => 'Fill in all the fields. This survey can be used in other parts of the site (for example, in posts).',
'poll_info' => 'My votes sorted by time.',
];

View file

@ -8,19 +8,22 @@
return [
'appealed_subject' => '{name} contacted you (@)',
'appealed_message' => '<p>On the site you were contacted (@). Look:<p><p>{url}/p>',
'appealed_message' => '<p>On the site you were contacted (@). Look:<p><p>{url}</p>',
'changing_password_subject' => '{name} — password recovery',
'changing_password_message' => '<p>Your password reset link:</p><p>{url}</p>',
'test_subject' => '{name} — mail testing (admin panel)',
'test_message' => '<p>This email is a test email sent through the admin panel.</p>',
'activate_email_subject' => '{name} — email activation',
'activate_email_message' => '<p>To continue registration, activate your E-mail. Follow this link:</p><p>{url}</p>',
'new_email_subject' => '{name} — change email',
'new_email_message' => '<p>To continue, activate your Email by clicking on the link:</p><p>{url}</p>',
'invite_reg_subject' => '{name} — invitation to join (invite)',
'invite_reg_message' => '<p>You have been invited to join the community. If you agree. then follow the link:</p><p>{url}</p>',
'footer' => '<p>This email was generated automatically.<br>You don\'t need to reply to it.</p><p>Administration.<br>{name}</p>',
];

View file

@ -8,46 +8,46 @@
return [
// Member profile
// Профиль участника
// Member profile
// Профиль участника
'profile_title' => '{name} — member profile ',
'profile_desc' => '{name} — member profile page. Posts, awards and contacts. {information}',
'profile_posts_title' => '{name} — post list ',
'profile_posts_all_desc' => '{name} — list of posts, articles of the participant in chronological order. All publications on the site.',
'profile_comments_title' => '{name} — participant\'s comments ',
'profile_comments_desc' => '{name} — participant\'s comments in chronological order. {information}',
// end
'all_users' => 'List of participants',
'all_users_info' => 'List of participants in the order of their activity on the site',
'all_users_info' => 'All participants registered on the site',
'all_users_desc' => 'Members arranged in order of their activity on the site. Ability to view profile information',
'new_users' => 'New Members',
'new_users_info' => 'List of members who have signed up to the site recently',
'new_users_desc' => 'Members who have registered on the site recently. Show activity, avatars, profile',
'all_blogs' => 'All blogs',
'all_blogs_info' => 'Blogs created by members',
'all_blogs_desc' => 'Blogs in the order of their registration on the site, the ability to view created blogs, subscribe to them, view statistics',
'new_blogs' => 'New blogs',
'new_blogs_info' => 'Blogs on the site added recently',
'new_blogs_desc' => 'Blogs on the site added recently. Personal blogs of participants, the possibility of subscribing to interesting blogs',
'new_blogs_desc' => 'Blogs on the site added recently. Personal blogs of participants, the possibility of subscribing to interesting blogs',
'my_blogs' => 'My blogs',
'my_blogs_info' => 'Blogs I follow or create',
'my_blogs_desc' => 'Blogs I read or created',
'all_topics' => 'All topics',
'all_topics_info' => 'All topics on the site in order of their popularity',
'all_topics_desc' => 'A page of topics arranged in order of popularity. By the number of posted posts, the ability to subscribe to blogs',
'new_topics' => 'New themes',
'new_topics' => 'New themes',
'new_topics_info' => 'New topics, topics added recently',
'new_topics_desc' => 'New themes added to the site recently. Topic statistics and the ability to subscribe to topics',
'my_topics' => 'I read',
'my_topics_info' => 'Topics I subscribe to',
'my_topics_desc' => 'Topics I read or created',
@ -56,11 +56,11 @@ return [
'comments_deleted_info' => 'Removed Comments...',
'answers_all_info' => 'All answers...',
'answers_deleted_info' => 'Deleted responses...',
'comments_desc' => 'All comments (per replies) in order of priority in the community',
'domain_desc' => 'Grouping posts in the community by domain',
'all_comments' => 'All comments',
'feed_facet_desc' => 'General feed. ',
'feed_facet_posts_desc' => 'Post feed. ',
'feed_facet_questions_desc' => 'Questions thread. ',

View file

@ -47,24 +47,29 @@ return [
'code_incorrect' => 'The code is incorrect or has already been used',
'yes_email_pass' => 'Now you can use your email and password.',
'email_replay' => 'This email is already on the site',
'email_forbidden' => 'Registration with the specified e-mail is forbidden',
'multiple_accounts' => 'Do not register multiple accounts',
'five_width' => 'Cover width less than 500px',
'five_format' => 'Wrong file type',
'silent_mode' => 'You cannot post content, your account is being verified',
'nick_character' => 'There are too many repeated characters in the nickname',
'nick_exist' => 'This nickname already exists',
'check_your_email' => 'Check your email to activate your account',
'new_email' => 'To activate the email, check the mail',
'user_already' => 'The user is already on the site',
'invate_replay' => 'You have already sent an invitation to this user',
'invate_limit_stop' => 'You have exhausted the number of invites',
'invite_created' => 'Invite created',
'url_reserved' => 'This blog URL is reserved',
'url_correctness' => 'URL is not correct',
'string_length' => 'Incorrect length {name}',
'slug_correctness' => '{name} must contain only Latin characters, numbers',
'email_correctness' => 'Invalid email',
'limit_day' => 'You have reached the limit for today',
'content_audit' => 'Your message has been sent for review',
'access_denied' => 'You are denied access',
'field_limit' => 'The number of fields has reached its maximum.',
];

View file

@ -18,4 +18,5 @@ return [
'sign_in' => 'Sign in',
'enter_password' => 'Enter password',
'under_reconstruction' => 'Site under reconstruction. Entrance for staff only.',
'under_maintenance' => 'Maintenance mode',
];

View file

@ -9,7 +9,7 @@
return [
'all' => 'All',
'posts' => 'Posts',
'answers' => 'Answers',
'comments' => 'Comments',
'websites' => 'Sites',
'registration' => 'Registration',
'sign_in' => 'To come in',
@ -25,4 +25,3 @@ return [
'help' => 'Site search and more...',
'query' => 'Query',
];

View file

@ -14,6 +14,7 @@ return [
'soft' => 'Soft',
'website' => 'Website',
'websites' => 'Sites',
'comments' => 'Comments',
'on_website' => 'To the website',
'deleted' => 'Remote',
'facets' => 'Facets',
@ -29,7 +30,8 @@ return [
'deny_replies' => 'Deny replies?',
'posted' => 'Posted?',
'necessarily' => 'Required to fill out',
'status' => 'Link Status',
'status' => 'Status',
'refresh' => 'Refresh',
'there_program' => 'There is a program?',
'there_forum' => 'The site has a forum?',
'there_portal' => 'Is this a portal?',
@ -41,6 +43,7 @@ return [
'related_posts' => 'Related posts',
'desc_formed' => 'Description is formed',
'by_date' => 'By date',
'top' => 'TOP',
'top_view' => 'By rating',
'new_sites' => 'New sites',
'audits_view' => 'Require consideration',
@ -73,7 +76,7 @@ return [
'audits_home_title' => 'Website audit',
'audits_home_desc' => 'Sites under consideration',
'num_website' => ['Site', 'Sites', 'Sites'],
'news' => 'News and Media',
'internet' => 'Internet',
'culture' => 'Culture and art',
@ -98,22 +101,21 @@ return [
'website_correctness' => 'The address (URL) of the site is not correct',
'site_replay' => 'Such a site already exists in the system',
'data_help' => '<i class="gray-600">Title Format:</i><br> «LibArea» — community<br><br><i class="gray-600">Description (no ads)):</i><br> ...what is on the site?<i>',
'data_help' => '<i class="gray-600">Title Format:</i><br> «LibArea» — community<br><br><i class="gray-600">Description (no ads)):</i><br> ...what is on the site?',
'admin_help' => 'Closed section available only to staff...',
'add_category' => 'Add category',
'add_website' => 'Add site',
'edit_website' => 'Edit site',
'sidebar_info' => 'Catalog of sites systematized by thematic headings.',
'banner_info' => 'Catalog of sites with annotations and screenshots. <br> Faceted rubrication, search. Bookmarks on resources with the ability to vote for sites, programs, rating',
'main_title' => 'Website directory',
'main_desc' => 'List of sites in the directory placed in chronological order. Ability to search, bookmark, sort by popularity',
'deleted_title' => 'Remote Sites',
'deleted_desc' => '...',
'audits_title' => 'Website audit',
'audits_desc' => '...',
'all' => 'All',
'github' => 'GitHub',

View file

@ -14,4 +14,3 @@ return [
'to_main' => 'Spre casă',
'error_404' => 'Eroare 404',
];

View file

@ -18,6 +18,8 @@ return [
'advertising' => 'Publicitate',
'catalog' => 'Catalog',
'facets' => 'Fațete',
'profile' => 'Profil',
'poll' => 'Studiu',
'users' => 'Membrii',
'time' => 'Timp',
'avatar' => 'Avatar',
@ -51,7 +53,7 @@ return [
'remove' => 'Șterge',
'completed' => 'Comanda finalizată',
'reward_user' => 'Recompensați participantul',
'topic' => 'Subiect',
'topics' => 'Subiecte',
'blog' => 'Blog',
@ -70,7 +72,7 @@ return [
'item' => 'Site-ul web',
'invite' => 'A invita',
'report' => 'O plangere',
'submenu' => 'submeniu',
'update' => 'Reîmprospăta',
'ban' => 'Interzice',
@ -86,6 +88,7 @@ return [
'contacts' => 'Contacte',
'tools' => 'Instrumente',
'trust_level' => 'Nivel de încredere',
'number_comments' => 'Numărul de comentarii',
'logs' => 'Bușteni',
'reports' => 'Steaguri (reclamații)',
'approve' => 'Aproba',
@ -112,27 +115,27 @@ return [
'tl4_title' => 'Regulat',
'tl5_title' => 'Lider',
'tl10_title' => 'Personal',
'deleted' => 'Îndepărtat',
'added' => 'Adăugat',
'restored' => 'Restaurat',
// Settings section
// Раздел настройки
'settings' => 'Setări',
'interface' => 'Interfață',
'functions' => 'Funcții',
'url_help' => 'Adresa URL a site-ului (cu https)',
'email_help' => 'E-mail public pentru comunicare',
'name_help' => 'Numele scurt al site-ului',
'title_help' => 'Numele complet al site-ului',
'img_path' => 'Calea către fotografie (intro pentru site)',
'img_path_help' => 'Folosit în og:image și în alte locuri când nu există o introducere în postare, de ex.',
'img_path_web' => 'Calea către fotografie (introducere pentru catalog)',
'img_path_web_help' => 'Folosit în og:image pentru directorul site-ului',
'banner_title' => 'Antet banner',
'banner_title_help' => 'Titlul bannerului pe pagina principală a site-ului, dacă participantul nu este autorizat',
'banner_desc' => 'Corpul bannerului',
@ -148,7 +151,7 @@ return [
'count_like_feed_help' => 'Câte aprecieri ar trebui să fie vizibile o postare pe pagina centrală a site-ului',
'type_post_feed' => 'Apariția postării în feed',
'type_post_feed_help' => 'Clasic sau Card. Dacă este clasic, atunci acesta este un design minimal',
'ads_home_post' => 'Pagina principală, feed, după 4 postări',
'ads_home_sidebar' => 'Pagina de pornire, bară laterală',
'ads_home_menu' => 'Pagina principală, meniul din stânga',

View file

@ -12,13 +12,17 @@ return [
'home' => 'Acasă',
'catalog' => 'Catalog',
'feed' => 'Flux',
'minimum' => 'Minim',
'poll' => 'Sondaj',
'polls' => 'Sondaje',
'closed' => 'Închis',
'hi' => 'Hei',
'news' => 'Știri',
'team' => 'Echipă',
'teams' => 'Echipe',
'subsections' => 'Subsecțiuni',
'table' => 'Masa',
'team_not_users' => 'Întrucât să nu știți...',
'total_votes' => 'Total de voturi',
'owner' => 'Proprietar',
'top' => 'Populare',
'one_month' => 'lună',
@ -88,7 +92,7 @@ return [
'write_message' => 'Pentru a scrie un mesaj',
'send' => 'Trimite',
'information' => 'Informație',
'donate' => 'Susține proiectul',
'donate' => 'Susține proiectul',
'review' => 'Revizuire',
'contacts' => 'Contacte',
'public_data' => 'Date publice vizibile în profil.',
@ -102,8 +106,9 @@ return [
'nickname' => 'Poreclă',
'name' => 'Nume',
'password' => 'Parola',
'new_password' => 'Parolă Nouă',
'repeat' => 'Repeta',
'new_password' => 'Parolă nouă',
'old_password' => 'Parola veche',
'confirm_password' => 'Repetați parola',
'show' => 'Spectacol',
'new' => 'Nou',
'new_ones' => 'Nou',
@ -165,7 +170,17 @@ return [
'drafts' => 'Ciorne',
'cancel' => 'Anulare',
'reply' => 'Răspuns',
'is_nsfw' => 'Activați vizualizarea conținutului pentru adulți și NSFW (+ miniaturi estompate) în feed.',
'nsfw_post' => 'Este adultul de conținut (NSFW)?',
'hidden_post' => 'Acces prin link?',
'hidden_post_help' => 'Numai utilizatorii cu link îl pot vedea.',
'delete_profile' => 'Ștergeți profilul',
'read_carefully' => 'Citiți cu atenție, este foarte important!',
'read_information' => 'Sunteți pe cale să vă ștergeți profilul. Pentru a șterge un profil, trebuie să confirmați că sunteți pregătit să ștergeți toate informațiile enumerate. Ștergerea unui profil este o <strong>acțiune ireversibilă</strong>, nu veți putea recupera datele pierdute.',
// Редактор
'foto' => 'A photo',
'bold' => 'îndrăzneţ',
@ -184,6 +199,8 @@ return [
'entry_policy' => 'Aprobați noi membri',
'option' => 'Opțiune',
'back' => 'Înapoi',
'edit' => 'Schimbare',
'save' => 'Salva',
@ -192,6 +209,8 @@ return [
'add_topic' => 'Adaugă subiect',
'add_blog' => 'Adaugă blog',
'add_category' => 'Adăugați o categorie',
'add_poll' => 'Adăugați sondaj',
'edit_poll' => 'Editați sondajul',
'edit_category' => 'Schimbați categoria',
'edit_post' => 'Editează postarea',
'edit_topic' => 'Editați subiectul',
@ -217,25 +236,26 @@ return [
'no_cover' => 'Nicio copertă încă',
'no_invites' => 'Nu ați creat invitații',
'no_content' => 'Ne pare rău, încă nu există conținut',
'no_dialogs' => 'Ne pare rău, încă nu există dialoguri',
'no_dialogs' => 'Ne pare rău, încă nu există dialoguri',
'no_posts' => 'Ne pare rău, încă nu există postări',
'no_favorites' => 'Ne pare rău, nu există încă marcaje',
'no_comments' => 'Din păcate, încă nu există comentarii',
'no_answers' => 'Ne pare rău, încă nu există răspunsuri',
'choose_dialogue' => 'Selectați un dialog de vizualizat',
'default' => 'Mod implicit',
'default' => '(mod implicit)',
'qa' => 'Întrebări și răspunsuri',
'best_answer' => 'Cel mai bun răspuns',
'raise_answer' => 'Ridicați răspunsul',
'answered' => 'Răspuns',
'post_translation' => 'Această postare este o traducere',
'translation' => 'Traducere',
'format_Q&A' => 'Aceasta este o întrebare (Q&A)',
'poll_closed' => 'Acest sondaj este închis?',
'pin' => 'Fixați această postare',
'source' => 'Sursa',
'website' => 'Site web',
'websites' => 'Site-uri web',
'sites' => 'Site-uri',
'related' => 'Legat',
'related_posts' => 'Postări similare',
'parinti' => 'parinti',
@ -284,7 +304,7 @@ return [
'forgot_password' => 'Ați uitat parola',
'rules' => 'Regulile site-ului',
'restriction' => 'Restricții',
'text_closed' => 'Fără autorizație este interzisă vizualizarea acestui text ascuns',
/* Дата и время + события */
@ -294,30 +314,21 @@ return [
'num_message' => ['Mesaj', 'Mesaje', 'Mesaje'],
'num_answer' => ['Răspuns', 'Răspuns', 'Răspunsuri'],
'num_comment' => ['Comentariu', 'Comentariu', 'Comentarii'],
'num_post' => ['Postează', 'Postează', 'Postează'],
'num_view' => ['Vizualizare', 'Vizualizare', 'Vizualizare'],
'num_up' => ['Voce', 'Voci', 'Voci'],
'comment' => 'Comentariu',
'comments' => 'Comentarii',
'answer' => 'Răspuns',
'answers' => 'Răspunsuri',
'message' => 'Mesaj',
'messages' => 'Mesaje',
'post' => 'Postare',
'posts' => 'Postări',
'comment' => 'Comentariu',
'comments' => 'Comentarii',
'answer' => 'Răspuns',
'answers' => 'Răspunsuri',
'message' => 'Mesaj',
'messages' => 'Mesaje',
'post' => 'Postare',
'posts' => 'Postări',
'language' => 'Localizare',
'ru_language' => 'Русский',
'ua_language' => 'Український',
'en_language' => 'English',
'de_language' => 'Deutsch',
'sk_language' => 'Slovenský',
'fr_language' => 'Français',
'zh_CN_language' => '简体中文',
'zh_TW_language' => '繁体中文',
'ro_language' => 'România',
'ar_language' => 'العربية',
'type' => 'Tip',
'logo' => 'Siglă',
@ -349,14 +360,14 @@ return [
'slug' => 'SLUG',
'email' => 'Email',
'wiki' => 'Wiki',
'edit_answer' => 'Să schimbăm răspunsul',
'edit_comment' => 'Schimbă comentariul',
'enter' => 'Introduce',
'enter_password' => 'Introdu parola',
'rec_posts' => 'postări recomandate',
'topic_subs' => 'Abonați-vă la subiecte și citiți-le în feed',
'i_read' => 'Citesc',
'message_PM' => 'Când a venit mesajul PM',
'appeal_@' => 'Când sunteți contactat prin @',
@ -380,21 +391,31 @@ return [
'invite_features' => 'Puteți invita prieteni',
'content_deleted' => '{name} îndepărtat',
'topic_deleted' => 'Subiectul a fost șters',
'facet_comments_disabled' => 'Dezactivați comentariile?',
'topic_comments_disabled' => 'Comentariile sunt dezactivate în subiect.',
'blog_comments_disabled' => 'Autorul blogului a dezactivat comentariile.',
'dir_comments_disabled' => 'Comentariile sunt dezactivate în această secțiune.',
'endless_scroll' => 'Activați derularea infinită?',
'notification_email' => 'Notificare prin e-mail',
'notifications_limit' => 'Se afișează ultimele 100 de notificări',
'ignored' => 'Ignorat',
'ignore' => 'Ignora',
'ignored' => 'Ignorat',
'ignored_users' => 'Utilizatori ignorați',
'ignored_users_help' => 'Utilizatori ale căror postări nu le vei vedea în feed.',
'ignored_no' => 'Nu aveți utilizatori pe care să-i ignorați.',
'ignored_no' => 'Nu aveți utilizatori pe care să-i ignorați.',
'not_confirmed' => 'neconfirmat.',
'resend_email' => 'Verificați-vă căsuța de e-mail sau retrimiteți un e-mail nou.',
/* Notificări */
'notif_add_pm' => 'ți-a trimis un {url}mesaj privat{a}',
'notif_add_comment' => 'a comentat {url}răspunsul tău{a}',
'notif_add_comment_comment' => 'a răspuns la {url}comentarul tău{a}',
'notif_add_answer' => 'a răspuns la {url}postarea ta{a}',
'notif_add_answer' => 'a răspuns la {url}postare{a}',
'notif_add_flag' => 'a primit {url}reclamație{a}',
'notif_add_audit' => '{url}auditul de conținut este necesar{a}',
'notif_references_post' => 'te-a menționat în {url}postare{a}',

View file

@ -10,7 +10,7 @@ return [
'mail_confirm' => 'După ce ați trimis formularul completat, vi se va cere să vă verificați adresa de e-mail. Este important să rețineți că nu veți putea trece prin restul procesului de îmbarcare până când nu veți face acest lucru.',
'login_info' => 'Autorizarea vă oferă posibilitatea de a publica postări, de a răspunde, de a comenta și de a vota.',
'invate_text' => 'Nu sunteți încă utilizator? Înregistrarea se face doar pe bază de invitație pentru a lupta împotriva spamului și pentru a crește responsabilitatea. Dacă cunoașteți <a href="/users">utilizatorul actual</a> al site-ului, cereți-i o invitație.',
// form validation on registration page
'nickname_empty' => 'Porecla nu poate fi goală.',
'nickname_least' => 'Porecla ar trebui să fie >= {info} caractere.',
@ -21,4 +21,3 @@ return [
'password_again' => 'Introduceți parola din nou.',
'password_mismatch' => 'Parola nepotrivită.',
];

View file

@ -33,4 +33,7 @@ return [
'team_info' => 'Puteți partaja blogul dvs. cu alți utilizatori, acordându-le acces.',
'draft_info' => 'Doar autorul poate citi schițele.',
'add_poll' => 'Completați toate câmpurile. Acest sondaj poate fi folosit în alte părți ale site-ului (de exemplu, în postări).',
'poll_info' => 'Voturile mele sunt sortate după timp.',
];

View file

@ -8,19 +8,22 @@
return [
'appealed_subject' => '{name} — ai fost contactat (@)',
'appealed_message' => '<p>Pe site, ați fost contactat (@). Uite:<p><p>{url}/p>',
'appealed_message' => '<p>Pe site, ați fost contactat (@). Uite:<p><p>{url}</p>',
'changing_password_subject' => '{name} — recuperare parola',
'changing_password_message' => '<p>Link pentru resetarea parolei:</p><p>{url}</p>',
'test_subject' => '{name} — testare e-mail (panoul de administrare)',
'test_message' => '<p>Acest e-mail este un e-mail de testare trimis prin panoul de administrare.</p>',
'activate_email_subject' => '{name} — activare prin e-mail',
'activate_email_message' => '<p>Pentru a continua înregistrarea, activați-vă adresa de e-mail. Urmați acest link:</p><p>{url}</p>',
'new_email_subject' => '{name} — schimbă e-mail',
'new_email_message' => '<p>Pentru a continua, activați-vă e-mailul făcând clic pe linkul:</p><p>{url}</p>',
'invite_reg_subject' => '{name} — invitație de a se alătura (invitație)',
'invite_reg_message' => '<p>Ați fost invitat să vă alăturați comunității. Dacă sunteți de acord. apoi urmați linkul:</p><p>{url}</p>',
'footer' => '<p>Acest e-mail a fost generat automat.<br>Nu trebuie să răspundeți la el.</p><p>Administrare.<br>{name}</p>',
];

View file

@ -8,46 +8,46 @@
return [
// Member profile
// Профиль участника
// Member profile
// Профиль участника
'profile_title' => '{name} — profilul membrului ',
'profile_desc' => '{name} — pagina de profil de membru. Postări, premii și contacte. {information}',
'profile_posts_title' => '{name} — lista de postări ',
'profile_posts_desc' => '{name} — lista de postări, articole ale participantului în ordine cronologică. Toate publicațiile de pe site.',
'profile_comments_title' => '{name} — comentariile participantului ',
'profile_comments_desc' => '{name} — comentariile participantului în ordine cronologică. {information}',
// end
'all_users' => 'Lista participanților',
'all_users_info' => 'Lista participanților în ordinea activității lor pe site',
'all_users_info' => 'Toți participanții s-au înscris pe site',
'all_users_desc' => 'Membrii aranjați în ordinea activității lor pe site. Posibilitatea de a vizualiza informațiile de profil',
'new_users' => 'Membri noi',
'new_users_info' => 'Lista membrilor care s-au înscris recent pe site',
'new_users_desc' => 'Membrii care s-au înregistrat recent pe site. Afișați activitatea, avatarele, profilul',
'all_blogs' => 'Toate blogurile',
'all_blogs_info' => 'Bloguri create de membrii',
'all_blogs_desc' => 'Bloguri în ordinea înregistrării lor pe site, posibilitatea de a vizualiza blogurile create, de a vă abona la ele, de a vizualiza statistici',
'new_blogs' => 'Bloguri noi',
'new_blogs_info' => 'Bloguri pe site adăugate recent',
'new_blogs_desc' => 'Bloguri pe site adăugate recent. Bloguri personale ale participanților, posibilitatea de a vă abona la bloguri interesante',
'new_blogs_desc' => 'Bloguri pe site adăugate recent. Bloguri personale ale participanților, posibilitatea de a vă abona la bloguri interesante',
'my_blogs' => 'Blogurile mele',
'my_blogs_info' => 'Bloguri pe care le urmăresc sau le creez',
'my_blogs_desc' => 'Bloguri pe care le-am citit sau creat',
'all_topics' => 'Toate subiectele',
'all_topics_info' => 'Toate subiectele de pe site în ordinea popularității lor',
'all_topics_desc' => 'O pagină cu subiecte aranjate în ordinea popularității. După numărul de postări postate, capacitatea de a te abona la bloguri',
'new_topics' => 'Teme noi',
'new_topics' => 'Teme noi',
'new_topics_info' => 'Subiecte noi, subiecte adăugate recent',
'new_topics_desc' => 'Teme noi adăugate recent pe site. Statisticile subiectelor și capacitatea de a te abona la subiecte',
'my_topics' => 'Citesc',
'my_topics_info' => 'Subiecte la care sunt abonat',
'my_topics_desc' => 'Subiecte pe care le-am citit sau creat',
@ -56,11 +56,11 @@ return [
'comments_deleted_info' => 'Comentarii eliminate...',
'answers_all_info' => 'Toate răspunsurile...',
'answers_deleted_info' => 'Răspunsuri șterse...',
'comments_desc' => 'Toate comentariile (pe răspunsuri) în ordinea priorității în comunitate',
'domain_desc' => 'Gruparea postărilor din comunitate după domeniu',
'all_comments' => 'Toate comentariile',
'feed_facet_desc' => 'Bandă generală. ',
'feed_facet_posts_desc' => 'Postați feedul. ',
'feed_facet_questions_desc' => 'Firul de întrebări. ',

View file

@ -47,24 +47,29 @@ return [
'code_incorrect' => 'Codul este incorect sau a fost deja folosit',
'yes_email_pass' => 'Acum vă puteți folosi adresa de e-mail și parola.',
'email_replay' => 'Acest e-mail este deja pe site',
'email_forbidden' => 'Înregistrarea la adresa de e-mail specificată este interzisă',
'multiple_accounts' => 'Nu înregistrați mai multe conturi',
'five_width' => 'Lățimea copertei mai mică de 500 px',
'five_format' => 'Tip de fișier greșit',
'silent_mode' => 'Nu poți posta conținut, contul tău este în curs de verificare',
'nick_character' => 'Există prea multe caractere repetate în porecla',
'nick_exist' => 'Această poreclă există deja',
'check_your_email' => 'Verificați e-mailul pentru a vă activa contul',
'new_email' => 'Verificați e-mailul pentru a activa e-mailul',
'user_already' => 'Utilizatorul este deja pe site',
'invate_replay' => 'Ați trimis deja o invitație acestui utilizator',
'invate_limit_stop' => 'Ați epuizat numărul de invitații',
'invite_created' => 'Invitație creată',
'url_reserved' => 'URL-ul acestui blog este rezervat',
'url_correctness' => 'URL-ul nu este corect',
'string_length' => 'Lungime incorectă {name}',
'slug_correctness' => '{name} trebuie să conțină numai caractere latine, numere',
'email_correctness' => 'E-mail invalid',
'limit_day' => 'Ai atins limita pentru azi',
'content_audit' => 'Mesajul dvs. a fost trimis spre examinare',
'access_denied' => 'Vi se interzice accesul',
'field_limit' => 'Numărul de câmpuri a atins maximul.',
];

View file

@ -18,4 +18,5 @@ return [
'sign_in' => 'Loghează-te',
'enter_password' => 'Introdu parola',
'under_reconstruction' => 'Site în reconstrucție. Intrarea numai pentru personal.',
'under_maintenance' => 'Modul de întreținere',
];

View file

@ -9,7 +9,7 @@
return [
'all' => 'Toate',
'posts' => 'Postări',
'answers' => 'Răspunsuri',
'comments' => 'Comentarii',
'websites' => 'Site-uri',
'registration' => 'Înregistrare',
'sign_in' => 'Conectare',
@ -25,4 +25,3 @@ return [
'help' => 'Căutare pe site și multe altele...',
'query' => 'Cerere',
];

View file

@ -14,6 +14,7 @@ return [
'soft' => 'Program',
'website' => 'Site-ul web',
'websites' => 'Site-uri',
'comments' => 'Comentarii',
'on_website' => 'Spre site',
'deleted' => 'la distanta',
'facets' => 'Fațete',
@ -29,7 +30,8 @@ return [
'deny_replies' => 'Respinge răspunsurile?',
'posted' => 'Postat?',
'necessarily' => 'Este necesar să se completeze',
'status' => 'Stare link',
'status' => 'Stare',
'refresh' => 'Reîmprospăta',
'there_program' => 'Există vreun program?',
'there_forum' => 'Site-ul are forum?',
'there_portal' => 'Acesta este un portal?',
@ -41,6 +43,7 @@ return [
'related_posts' => 'Postări asemănatoare',
'desc_formed' => 'Se formează descrierea',
'by_date' => 'După dată',
'top' => 'TOP',
'top_view' => 'Prin rating',
'new_sites' => 'Site-uri noi',
'audits_view' => 'Necesită luare în considerare',
@ -69,11 +72,11 @@ return [
'closed' => 'Discuțiile despre site sunt interzise. Autorul sau personalul a închis discuția.',
'screenshot_time' => 'Realizarea unei capturi de ecran poate dura ceva timp.',
'audits_home_title' => 'Auditul site-ului',
'audits_home_desc' => 'Site-uri luate în considerare',
'num_website' => ['Site-ul web', 'Site', 'Site-uri'],
'news' => 'Știri și mass-media',
'internet' => 'Internet',
'culture' => 'Cultură și artă',
@ -99,22 +102,21 @@ return [
'website_correctness' => 'Adresa (URL) site-ului nu este corectă',
'site_replay' => 'Un astfel de site există deja în sistem',
'data_help' => '<i class="gray-600">Format antet:</i><br> «LibArea» — comunitate<br><br><i class="gray-600">Descriere (fără reclame):</i><br> ...ce este pe site?<i>',
'data_help' => '<i class="gray-600">Format antet:</i><br> «LibArea» — comunitate<br><br><i class="gray-600">Descriere (fără reclame):</i><br> ...ce este pe site?',
'admin_help' => 'Secțiune închisă disponibilă numai personalului',
'add_category' => 'Adăugați o categorie',
'add_website' => 'Adăugați site',
'edit_website' => 'Editați site-ul',
'sidebar_info' => 'Catalog de site-uri sistematizate pe rubrici tematice.',
'banner_info' => 'Catalog de site-uri cu adnotări și capturi de ecran. <br> Rubricare fațetă, căutare. Marcaje pe resurse cu posibilitatea de a vota site-uri, programe, rating',
'main_title' => 'Director de site-uri',
'main_desc' => 'Lista site-urilor din director plasate în ordine cronologică. Abilitatea de a căuta, marca, sorta după popularitate',
'deleted_title' => 'Site-uri la distanță',
'deleted_desc' => '...',
'audits_title' => 'Auditul site-ului',
'audits_desc' => '...',
'all' => 'Toate',
'github' => 'GitHub',

View file

@ -18,6 +18,8 @@ return [
'advertising' => 'Реклама',
'catalog' => 'Каталог',
'facets' => 'Фасеты',
'profile' => 'Профиль',
'poll' => 'Опрос',
'users' => 'Участники',
'time' => 'Время',
'avatar' => 'Аватар',
@ -86,6 +88,7 @@ return [
'contacts' => 'Контакты',
'tools' => 'Инструменты',
'trust_level' => 'Уровень доверия',
'number_comments' => 'Количество комментариев',
'logs' => 'Логи',
'reports' => 'Флаги (жалобы)',
'approve' => 'Одобрить',

View file

@ -12,15 +12,19 @@ return [
'home' => 'Главная',
'catalog' => 'Каталог',
'feed' => 'Лента',
'minimum' => 'Минимальный',
'poll' => 'Голосование',
'polls' => 'Голосования',
'closed' => 'Закрыто',
'hi' => 'Привет',
'news' => 'Новость',
'team' => 'Команда',
'teams' => 'Команды',
'subsections' => 'Подразделы',
'table' => 'Таблица',
'team_not_users' => 'В команде пока нет участников...',
'total_votes' => 'Всего голосовало',
'owner' => 'Владелец',
'top' => 'TOP',
'top' => 'ТОП',
'one_month' => 'месяц',
'three_months' => '3 месяца',
'all_time' => 'всё время',
@ -103,7 +107,8 @@ return [
'name' => 'Имя',
'password' => 'Пароль',
'new_password' => 'Новый пароль',
'repeat' => 'Повторите',
'old_password' => 'Старый пароль',
'confirm_password' => 'Повторите пароль',
'show' => 'Показывать',
'new' => 'Новый',
'new_ones' => 'Новые',
@ -166,6 +171,16 @@ return [
'cancel' => 'Отменить',
'reply' => 'Ответить',
'is_nsfw' => 'Включите просмотр контента для взрослых и NSFW (+ размытие миниатюр) в ленте.',
'nsfw_post' => 'Является ли контент для взрослых (NSFW)?',
'hidden_post' => 'Доступ по ссылке?',
'hidden_post_help' => 'Его смогут увидеть только пользователи, у которых есть ссылка.',
'delete_profile' => 'Удалить профиль',
'read_carefully' => 'Прочтите внимательно, это действительно важно!',
'read_information' => 'Вы собираетесь удалить свой профиль. Для удаления профиля необходимо подтвердить, что вы готовы к удалению всей перечисленной информации. Удаление профиля <strong>необратимое действие</strong>, вы не сможете вернуть утерянные данные.',
// Редактор
'foto' => 'Фото',
'bold' => 'Жирный',
@ -184,6 +199,8 @@ return [
'entry_policy' => 'Утверждать вступивших участников',
'option' => 'Вариант',
'back' => 'Назад',
'edit' => 'Изменить',
'save' => 'Сохранить',
@ -192,13 +209,15 @@ return [
'add_topic' => 'Добавить тему',
'add_blog' => 'Добавить блог',
'add_category' => 'Добавить категорию',
'add_poll' => 'Добавить опрос',
'edit_poll' => 'Изменить опрос',
'edit_category' => 'Изменить категорию',
'edit_post' => 'Изменить пост',
'edit_topic' => 'Изменить тему',
'edit_blog' => 'Изменить блог',
'edit_page' => 'Изменить страницу',
'edit_section' => 'Изменить раздел',
'share_post' => 'Поделиться Постом',
'share_topic' => 'Поделиться Темой',
'share_blog' => 'Поделиться Блогом',
@ -223,19 +242,20 @@ return [
'no_comments' => 'К сожалению, комментариев пока нет',
'no_answers' => 'К сожалению, ответов пока нет',
'choose_dialogue' => 'Выберите диалог для просмотра',
'default' => 'По умолчанию',
'default' => '(по умолчанию)',
'qa' => 'Вопросы и ответы',
'best_answer' => 'Лучший ответ',
'raise_answer' => 'Поднять ответ',
'answered' => 'Ответили',
'post_translation' => 'Пост является переводом?',
'translation' => 'Перевод',
'format_Q&A' => 'Это вопрос (станет форматом Q&A)?',
'poll_closed' => 'Этот опрос закрыт?',
'pin' => 'Закрепить данный пост?',
'source' => 'Источник',
'website' => 'Сайт',
'websites' => 'Сайты',
'sites' => 'Сайты',
'related' => 'Связанное',
'related_posts' => 'Связанные посты',
'parents' => 'Родители',
@ -294,6 +314,7 @@ return [
'num_message' => ['Сообщение', 'Сообщения', 'Сообщений'],
'num_answer' => ['Ответ', 'Ответа', 'Ответов'],
'num_comment' => ['Комментарий', 'Комментария', 'Комментариев'],
'num_post' => ['Пост', 'Поста', 'Постов'],
'num_view' => ['Просмотр', 'Просмотра', 'Просмотров'],
'num_up' => ['Голос', 'Голоса', 'Голосов'],
@ -308,16 +329,6 @@ return [
'posts' => 'Посты',
'language' => 'Локализация',
'ru_language' => 'Русский',
'ua_language' => 'Український',
'en_language' => 'English',
'de_language' => 'Deutsch',
'sk_language' => 'Slovenský',
'fr_language' => 'Français',
'zh_CN_language' => '简体中文',
'zh_TW_language' => '繁体中文',
'ro_language' => 'România',
'ar_language' => 'العربية',
'type' => 'Тип',
'logo' => 'Логотип',
@ -349,7 +360,7 @@ return [
'slug' => 'SLUG',
'email' => 'Email',
'wiki' => 'Wiki',
'edit_answer' => 'Изменим ответ',
'edit_comment' => 'Изменим комментарий',
'enter' => 'Введите',
'enter_password' => 'Введите пароль',
@ -380,21 +391,31 @@ return [
'invite_features' => 'Вы можете пригласить друзей',
'content_deleted' => '{name} удален',
'topic_deleted' => 'Тема удалена',
'facet_comments_disabled' => 'Запретить комментарии?',
'topic_comments_disabled' => 'В Tеме отключены комментарии.',
'blog_comments_disabled' => 'Автор Блога отключил комментарии.',
'dir_comments_disabled' => 'В данном Разделе комментарии выключены.',
'endless_scroll' => 'Включить скролл в ленте?',
'notification_email' => 'Уведомлять по E-mail',
'notifications_limit' => 'Показаны последние 100 уведомлений',
'ignore' => 'Игнорировать',
'ignored' => 'Игнорированные',
'ignored_users' => 'Игнорированные участники',
'ignored_users_help' => 'Пользователи, чьи посты вы не будете видеть в ленте.',
'ignored_no' => 'У вас нет пользователей, которые вы игнорируете.',
'not_confirmed' => 'не подтвержден.',
'resend_email' => 'Проверьте свою почту или повторно отправьте новый email.',
/* Уведомления */
'notif_add_pm' => 'написал вам {url}личное сообщение{a}',
'notif_add_comment' => 'прокомментировал {url}ваш ответ{a}',
'notif_add_comment_comment' => 'ответил на {url}ваш комментарий{a}',
'notif_add_answer' => 'ответил на {url}ваш пост{a}',
'notif_add_answer' => 'ответил на {url}пост{a}',
'notif_add_flag' => 'поступила {url}жалоба{a}',
'notif_add_audit' => 'требуется {url}аудит контента{a}',
'notif_references_post' => 'упомянул вас в {url}посте{a}',

View file

@ -10,7 +10,7 @@ return [
'mail_confirm' => 'После отправки заполненной формы вам будет предложено подтвердить адрес электронной почты. Важно отметить, что вы не сможете пройти остальную часть процесса адаптации, пока не сделаете этого.',
'login_info' => 'Авторизация дает возможность публиковать посты, отвечать, комментировать и голосовать.',
'invate_text' => 'Еще не пользователь? Регистрация осуществляется только по приглашению для борьбы со спамом и повышения ответственности. Если вы знаете <a href="/users">текущего пользователя</a> сайта, попросите у него приглашение.',
// form validation on registration page
'nickname_empty' => 'Никнейм не может быть пустым.',
'nickname_least' => 'Никнейм должно быть >= {info} символов.',

View file

@ -33,4 +33,7 @@ return [
'team_info' => 'Ваш Блог можно вести совместно с другими пользователями — для этого вам нужно предоставить им доступ.',
'draft_info' => 'Читать черновики может только автор.',
'add_poll' => 'Заполните все поля. Данный опрос можно будет использовать в других частях сайта (например, в постах).',
'poll_info' => 'Мои голосования сортированные по времени.',
];

View file

@ -8,7 +8,7 @@
return [
'appealed_subject' => '{name} — к вам обратились (@)',
'appealed_message' => '<p>На сайте, к вам обратились (@). Посмотреть:<p><p>{url}/p>',
'appealed_message' => '<p>На сайте, к вам обратились (@). Посмотреть:<p><p>{url}</p>',
'changing_password_subject' => '{name} — восстановление пароля',
'changing_password_message' => '<p>Ваша ссылка для изменения пароля:</p><p>{url}</p>',
@ -19,6 +19,9 @@ return [
'activate_email_subject' => '{name} — активация email',
'activate_email_message' => '<p>Для продолжения регистрации активируйте свой E-mail. Перейдите по ссылке:</p><p>{url}</p>',
'new_email_subject' => '{name} — смена email',
'new_email_message' => '<p>Для продолжения, активируйте свой E-mail перейдя по ссылке:</p><p>{url}</p>',
'invite_reg_subject' => '{name} — приглашение присоединиться (инвайт)',
'invite_reg_message' => '<p>Вас пригласили присоединиться к сообществу. Если вы согласны. то перейдите по ссылке:</p><p>{url}</p>',

View file

@ -21,7 +21,7 @@ return [
// end
'all_users' => 'Список участников',
'all_users_info' => 'Список участников в порядке их активности на сайте',
'all_users_info' => 'Все участники зарегистрированные на сайте',
'all_users_desc' => 'Участники расположенные в порядке их активности на сайте. Возможность просматривать данные профиля',
'new_users' => 'Новые участники',
@ -61,7 +61,7 @@ return [
'domain_desc' => 'Группировка постов в сообществе по домену.',
'all_comments' => 'Все комментарии',
'feed_facet_desc' => 'Общая лента. ',
'feed_facet_posts_desc' => 'Лента постов. ',
'feed_facet_questions_desc' => 'Лента вопросов. ',

View file

@ -47,12 +47,15 @@ return [
'code_incorrect' => 'Код неверен, или он уже использовался',
'yes_email_pass' => 'Теперь вы можете использовать свой e-mail и пароль.',
'email_replay' => 'Такой e-mail уже есть на сайте',
'email_forbidden' => 'Запрещена регистрация с указанным e-mail',
'multiple_accounts' => 'Не регистрируйте множественные аккаунты',
'five_width' => 'Ширина обложки меньше 500px',
'five_format' => 'Неверный тип файла',
'silent_mode' => 'Вы не можете публиковать материалы, ваш аккаунт проверяется',
'nick_character' => 'В никнейме слишком много повторяющихся символов',
'nick_exist' => 'Такой никнейм уже существует',
'check_your_email' => 'Проверьте e-mail почту для активации аккаунта',
'new_email' => 'Чтобы активировать e-mail, проверьте почту',
'user_already' => 'Пользователь уже есть на сайте',
'invate_replay' => 'Вы уже отправили приглашение этому пользователю',
'invate_limit_stop' => 'Вы исчерпали количество инвайтов',
@ -67,4 +70,6 @@ return [
'limit_day' => 'Вы исчерпали лимит на сегодня',
'content_audit' => 'Ваше сообщение отправлено на проверку',
'access_denied' => 'Вам отказано в доступе',
'field_limit' => 'Число полей достигло своего максимума.',
];

View file

@ -16,4 +16,5 @@ return [
'sign_in' => 'Войти',
'enter_password' => 'Введите пароль',
'under_reconstruction' => 'Сайт на реконструкции. Вход только для персонала.',
'under_maintenance' => 'Режим технического обслуживания',
];

View file

@ -9,7 +9,7 @@
return [
'all' => 'Все',
'posts' => 'Посты',
'answers' => 'Ответы',
'comments' => 'Комментарии',
'websites' => 'Сайты',
'registration' => 'Регистрация',
'sign_in' => 'Войти',

View file

@ -14,6 +14,7 @@ return [
'soft' => 'Софт',
'website' => 'Сайт',
'websites' => 'Сайты',
'comments' => 'Комментарии',
'on_website' => 'На сайт',
'deleted' => 'Удаленные',
'facets' => 'Фасеты',
@ -29,7 +30,8 @@ return [
'deny_replies' => 'Запретить ответы?',
'posted' => 'Размещен?',
'necessarily' => 'Обязательно к заполнению',
'status' => 'Статус ссылки',
'status' => 'Статус',
'refresh' => 'Обновить',
'there_program' => 'Есть программа?',
'there_forum' => 'На сайте есть форум?',
'there_portal' => 'Это портал?',
@ -41,6 +43,7 @@ return [
'related_posts' => 'Связанные посты',
'desc_formed' => 'Описание формируется',
'by_date' => 'По дате',
'top' => 'ТОП',
'top_view' => 'По рейтингу',
'new_sites' => 'Новые сайты',
'audits_view' => 'Требуют рассмотрения',
@ -98,7 +101,8 @@ return [
'website_correctness' => 'Адрес (URL) сайта не является корректным',
'site_replay' => 'Такой сайт уже есть в системе',
'data_help' => '<i class="gray-600">Формат заголовка:</i><br> «LibArea» — сообщество<br><br><i class="gray-600">Описание (без рекламы):</i><br> ...что есть на сайте?<i>',
'data_help' => '<i class="gray-600">Формат заголовка:</i><br> «LibArea» — сообщество<br><br><i class="gray-600">Описание (без рекламы):</i><br> ...что есть на сайте?',
'admin_help' => 'Закрытый раздел доступный только персоналу...',
'add_category' => 'Добавить категорию',
'add_website' => 'Добавить сайт',
@ -111,9 +115,7 @@ return [
'main_desc' => 'Список сайтов в каталоге размещенных в хронологическом порядке. Возможность поиска, закладки, сортировка по популярности',
'deleted_title' => 'Удаленные сайты',
'deleted_desc' => '...',
'audits_title' => 'Аудит сайтов',
'audits_desc' => '...',
'all' => 'Все',
'github' => 'GitHub',

View file

@ -12,4 +12,3 @@ return [
'to_main' => 'На головну',
'error_404' => 'Помилка 404',
];

View file

@ -18,6 +18,8 @@ return [
'advertising' => 'Реклама',
'catalog' => 'Каталог',
'facets' => 'Фасети',
'profile' => 'Профіль',
'poll' => 'Опитування',
'users' => 'Учасники',
'time' => 'Час',
'avatar' => 'Аватар',
@ -51,7 +53,7 @@ return [
'remove' => 'Вилучити',
'completed' => 'Команда виконана',
'reward_user' => 'Нагородити учасника',
'topic' => 'Тема',
'topics' => 'Теми',
'blog' => 'Блог',
@ -70,7 +72,7 @@ return [
'item' => 'Сайт',
'invite' => 'Інвайт',
'report' => 'Скарга',
'submenu' => 'субменю',
'update' => 'Оновити',
'ban' => 'Забанити',
@ -86,6 +88,7 @@ return [
'contacts' => 'Контакти',
'tools' => 'Інструменти',
'trust_level' => 'Рівень довіри',
'number_comments' => 'Кількість коментарів',
'logs' => 'Логи',
'reports' => 'Прапори (скарги)',
'approve' => 'Схвалити',
@ -112,7 +115,7 @@ return [
'tl4_title' => 'Завзятий',
'tl5_title' => 'Лідер',
'tl10_title' => 'Персонал',
'deleted' => 'Вилучений',
'added' => 'Доданий',
'restored' => 'Відновлено',
@ -122,17 +125,17 @@ return [
'settings' => 'Налаштування',
'interface' => 'Інтерфейс',
'functions' => 'Функції',
'url_help' => 'URL сайту (з https)',
'email_help' => 'Публічний Email для зв\'язку',
'name_help' => 'Коротке ім\'я сайту',
'title_help' => 'Повне ім\'я сайту',
'img_path' => 'Шлях до фотографії (заставка для сайту)',
'img_path_help' => 'Використовується в og:image та в інших місцях, коли в посту немає заставки, наприклад.',
'img_path_web' => 'Шлях до фотографії (заставка для каталогу)',
'img_path_web_help' => 'Використовується в og:image для каталогу сайтів',
'banner_title' => 'Заголовок банера',
'banner_title_help' => 'Заголовок баннера на головній сторінці сайту, якщо учасник без авторизації',
'banner_desc' => 'Тіло банера',
@ -148,7 +151,7 @@ return [
'count_like_feed_help' => 'Скільки лайків має набрати пост, щоб було видно на центральній сторінці сайту',
'type_post_feed' => 'Зовнішній вигляд посту у стрічці',
'type_post_feed_help' => 'Classic або Card. Якщо Classic, то це мінімальний дизайн',
'ads_home_post' => 'Головна сторінка, стрічка, після 4 посту',
'ads_home_sidebar' => 'Головна сторінка, бічна колонка',
'ads_home_menu' => 'Головна сторінка, ліве меню',

View file

@ -12,13 +12,17 @@ return [
'home' => 'Головна',
'catalog' => 'Каталог',
'feed' => 'Стрічка',
'minimum' => 'Мінімум',
'poll' => 'Опитування',
'polls' => 'Опитування',
'closed' => 'Зачинено',
'hi' => 'Привіт',
'news' => 'Новина',
'team' => 'Команда',
'teams' => 'Команди',
'subsections' => 'Підрозділи',
'table' => 'Таблиця',
'team_not_users' => 'У команді поки немає учасників...',
'total_votes' => 'Усього голосувало',
'owner' => 'Власник',
'top' => 'TOP',
'one_month' => 'місяць',
@ -88,7 +92,7 @@ return [
'write_message' => 'Написати повідомлення',
'send' => 'Надіслати',
'information' => 'Інформація',
'donate' => '<span class="red">П</span>ідтримайте проект',
'donate' => '<span class="red">П</span>ідтримайте проект',
'review' => 'Огляд',
'contacts' => 'Контакти',
'public_data' => 'Публічні дані, видимі у профілі.',
@ -103,7 +107,8 @@ return [
'name' => 'Ім\'я',
'password' => 'Пароль',
'new_password' => 'Новий пароль',
'repeat' => 'Повторіть',
'old_password' => 'Старий пароль',
'confirm_password' => 'Повторіть пароль',
'show' => 'Показувати',
'new' => 'Новий',
'new_ones' => 'Нові',
@ -165,7 +170,17 @@ return [
'drafts' => 'Чернетки',
'cancel' => 'Скасувати',
'reply' => 'Відповісти',
'is_nsfw' => 'Увімкніть перегляд контенту для дорослих та NSFW (+ розмиття мініатюр) у стрічці.',
'nsfw_post' => 'Чи є контент для дорослих (NSFW)?',
'hidden_post' => 'Доступ за посиланням?',
'hidden_post_help' => 'Лише користувачі з посиланням можуть бачити його.',
'delete_profile' => 'Видалити профіль',
'read_carefully' => 'Прочитайте уважно, це справді важливо!',
'read_information' => 'Ви збираєтесь видалити свій профіль. Для видалення профілю необхідно підтвердити, що ви готові видалити всю перелічену інформацію. Видалення профілю <strong>необоротна дія</strong>, ви не зможете повернути втрачені дані.',
// Редактор
'foto' => 'Фото',
'bold' => 'Жирний',
@ -181,9 +196,11 @@ return [
'select_image' => 'Please select an image',
'drop_image' => 'Перетягніть зображення, щоб завантажити його.',
'attach_files' => 'Файли можна вставляти з буфера.',
'entry_policy' => 'Стверджувати учасників, що вступили',
'option' => 'Варіант',
'back' => 'Назад',
'edit' => 'Змінити',
'save' => 'Зберегти',
@ -192,6 +209,8 @@ return [
'add_topic' => 'Додати тему',
'add_blog' => 'Додати блог',
'add_category' => 'Додати категорію',
'add_poll' => 'Додати опитування',
'edit_poll' => 'Змінити опитування',
'edit_category' => 'Змінити категорію',
'edit_post' => 'Змінити пост',
'edit_topic' => 'Змінити тему',
@ -205,7 +224,7 @@ return [
'share_website' => 'Поділитися сайтом',
'my_blog' => 'Мій блог',
'published' => 'Опубліковано',
'being_developed' => 'У стадії розробки',
@ -223,19 +242,20 @@ return [
'no_comments' => 'На жаль, коментарів поки немає',
'no_answers' => 'На жаль, відповідей поки немає',
'choose_dialogue' => 'Виберіть діалог для перегляду',
'default' => 'За замовчуванням',
'default' => '(за замовчуванням)',
'qa' => 'Питання та відповіді',
'best_answer' => 'Найкраща відповідь',
'raise_answer' => 'Підняти відповідь',
'answered' => 'Відповіли',
'post_translation' => 'Піст є перекладом?',
'translation' => 'Переклад',
'format_Q&A' => 'Це питання (стане форматом Q&A)?',
'poll_closed' => 'Це опитування закрите?',
'pin' => 'Закріпити цей пост?',
'source' => 'Джерело',
'website' => 'Сайт',
'websites' => 'Сайти',
'sites' => 'Сайти',
'related' => 'Пов\'язане',
'related_posts' => 'Пов\'язані пости',
'parents' => 'Батьки',
@ -284,7 +304,7 @@ return [
'forgot_password' => 'Забули пароль',
'rules' => 'Правила сайту',
'restriction' => 'Обмеження',
'text_closed' => 'Без авторизації заборонено переглядати цей прихований текст',
/* Дата та час + події */
@ -294,6 +314,7 @@ return [
'num_message' => ['Повідомлення', 'Повідомлення', 'Повідомлень'],
'num_answer' => ['Відповідь', 'Відповіді', 'Відповідей'],
'num_comment' => ['Коментар', 'Коментаря', 'Коментарів'],
'num_post' => ['Пост', 'Поста', 'Постів'],
'num_view' => ['Перегляд', 'Перегляду', 'Переглядів'],
'num_up' => ['Голос', 'Голосу', 'Голосів'],
@ -308,16 +329,6 @@ return [
'posts' => 'Пости',
'language' => 'Локалізація',
'ru_language' => 'Русский',
'ua_language' => 'Український',
'en_language' => 'English',
'de_language' => 'Deutsch',
'sk_language' => 'Slovenský',
'fr_language' => 'Français',
'zh_CN_language' => '简体中文',
'zh_TW_language' => '繁体中文',
'ro_language' => 'România',
'ar_language' => 'العربية',
'type' => 'Тип',
'logo' => 'Логотип',
@ -349,14 +360,14 @@ return [
'slug' => 'SLUG',
'email' => 'Email',
'wiki' => 'Wiki',
'edit_answer' => 'Змінимо відповідь',
'edit_comment' => 'Змінимо коментар',
'enter' => 'Введіть',
'enter_password' => 'Введіть пароль',
'rec_posts' => 'рекомендовані пости',
'topic_subs' => 'Підпишіться на теми та читайте їх у стрічці',
'i_read' => 'Я прочитав',
'message_PM' => 'Коли надійшло повідомлення на PM',
'appeal_@' => 'Коли звернулися до мене через @',
@ -380,21 +391,31 @@ return [
'invite_features' => 'Ви можете запросити друзів',
'content_deleted' => '{name} видалено',
'topic_deleted' => 'Тема видалена',
'facet_comments_disabled' => 'Заборонити коментарі?',
'topic_comments_disabled' => 'У темі відключені коментарі.',
'blog_comments_disabled' => 'Автор Блога відключив коментарі.',
'dir_comments_disabled' => 'У цьому Розділі коментарі вимкнені.',
'endless_scroll' => 'Увімкнути скролл у стрічці?',
'notification_email' => 'Повідомляти по E-mail',
'notifications_limit' => 'Показано останні 100 повідомлень',
'ignored' => 'Ігноровані',
'ignore' => 'Нехтувати',
'ignored' => 'Ігноровані',
'ignored_users' => 'Ігноровані учасники',
'ignored_users_help' => 'Користувачі, чиї пости ви не бачитимете у стрічці.',
'ignored_no' => 'Ви не маєте користувачів, які ви ігноруєте.',
'ignored_no' => 'Ви не маєте користувачів, які ви ігноруєте.',
'not_confirmed' => 'не підтверджено.',
'resend_email' => 'Перевірте свою електронну скриньку або надішліть новий електронний лист ще раз.',
/* Повідомлення */
'notif_add_pm' => 'написав вам {url}особисте повідомлення{a}',
'notif_add_comment' => 'прокоментував {url}ваша відповідь{a}',
'notif_add_comment_comment' => 'відповів на {url}ваш коментар{a}',
'notif_add_answer' => 'відповів на {url}ваш пост{a}',
'notif_add_answer' => 'відповів на {url}пост{a}',
'notif_add_flag' => 'надійшла {url}скарга{a}',
'notif_add_audit' => 'потрібно {url}аудит контенту{a}',
'notif_references_post' => 'згадав вас в {url}після{a}',

View file

@ -10,7 +10,7 @@ return [
'mail_confirm' => 'Після надсилання заповненої форми вам буде запропоновано підтвердити адресу електронної пошти. Важливо, що ви зможете пройти решту процесу адаптації, доки зробите цього.',
'login_info' => 'Авторизація дає можливість публікувати пости, відповідати, коментувати та голосувати.',
'invate_text' => 'Ще не користувач? Реєстрація здійснюється тільки на запрошення для боротьби зі спамом та підвищення відповідальності. Якщо ви знаєте <a href="/users">поточного користувача</a> сайту, попросіть у нього запрошення.',
// form validation on registration page
'nickname_empty' => 'Нікнейм не може бути порожнім.',
'nickname_least' => 'Нікнейм має бути >= {info} символів.',
@ -21,4 +21,3 @@ return [
'password_again' => 'Введіть пароль ще раз.',
'password_mismatch' => 'Паролі не співпадають.',
];

View file

@ -33,4 +33,7 @@ return [
'team_info' => 'Ваш Блог можна вести спільно з іншими користувачами для цього вам потрібно надати їм доступ.',
'draft_info' => 'Читати чернетки може лише автор.',
'add_poll' => 'Заповніть всі поля. Це опитування можна буде використовувати в інших частинах сайту (наприклад, у постах).',
'poll_info' => 'Мої голосування сортовані за часом.',
];

View file

@ -8,20 +8,23 @@
return [
'appealed_subject' => '{name} — до вас звернулися (@)',
'appealed_message' => '<p>На сайті, до вас звернулися (@). Переглянути:<p><p>{url}/p>',
'appealed_message' => '<p>На сайті, до вас звернулися (@). Переглянути:<p><p>{url}</p>',
'changing_password_subject' => '{name} — відновлення паролю',
'changing_password_message' => '<p>Ваше посилання для зміни пароля:</p><p>{url}</p>',
'test_subject' => '{name} — тестування пошти (адмін-панель)',
'test_message' => '<p>Цей лист є тестовим, надісланим через адмін-панель.</p>',
'activate_email_subject' => '{name} активація email',
'activate_email_message' => '<p>Щоб продовжити реєстрацію, активуйте свій E-mail. Перейдіть за посиланням:</p><p>{url}</p>',
'new_email_subject' => '{name} — зміна email',
'new_email_message' => '<p>Для продовження, активуйте свій E-mail, перейшовши за посиланням:</p><p>{url}</p>',
'invite_reg_subject' => '{name} — запрошення приєднатися (інвайт)',
'invite_reg_message' => '<p>Вас запросили приєднатися до спільноти. Якщо ви згодні. то перейдіть за посиланням:</p><p>{url}</p>',
'footer' => '<p>Цей лист створено автоматично.<br>Відповідати на нього не треба.</p><p>Адміністрація.<br>{name}</p>',
];

View file

@ -8,46 +8,46 @@
return [
// Member profile
// Профиль участника
// Member profile
// Профиль участника
'profile_title' => '{name} — профіль користувача ',
'profile_desc' => '{name} — сторінка профілю користувача. Пости, нагороди та контакти. {information}',
'profile_posts_title' => '{name} — список постів ',
'profile_posts_desc' => '{name} — список постів, статей учасника у хронологічному порядку. Усі публікації на сайті.',
'profile_posts_desc' => '{name} — список постів, статей учасника у хронологічному порядку. Усі публікації на сайті.',
'profile_comments_title' => '{name} — коментарі учасника ',
'profile_comments_desc' => '{name} — коментарі учасника у хронологічному порядку. {information}',
// end
'all_users' => 'Список учасників',
'all_users_info' => 'Список учасників у порядку їх активності на сайті',
'all_users_info' => 'Усі учасники зареєстровані на сайті',
'all_users_desc' => 'Учасники розміщені в порядку їхньої активності на сайті. Можливість перегляду даних профілю',
'new_users' => 'Нові учасники',
'new_users_info' => 'Список учасників, які зареєструвалися на сайт останнім часом',
'new_users_desc' => 'Учасники, які реєструвалися на сайті останнім часом. Виявляють активність, аватарки, профіль',
'all_blogs' => 'Усі блоги',
'all_blogs_info' => 'Блоги створені учасниками',
'all_blogs_desc' => 'Блоги в порядку їх реєстрації на сайті, можливість переглядати створені блоги, підписуватись на них, переглядати статистику',
'new_blogs' => 'Нові блоги',
'new_blogs_info' => 'Блоги на сайті додані останнім часом',
'new_blogs_desc' => 'Блоги на сайті додані останнім часом. Особисті блоги учасників, можливість підписки на цікаві блоги',
'new_blogs_desc' => 'Блоги на сайті додані останнім часом. Особисті блоги учасників, можливість підписки на цікаві блоги',
'my_blogs' => 'Мої блоги',
'my_blogs_info' => 'Блоги, на які я підписаний, або створив',
'my_blogs_desc' => 'Блоги, які я читаю чи створив',
'all_topics' => 'Усі теми',
'all_topics_info' => 'Всі теми на сайті в порядку їхньої популярності',
'all_topics_desc' => 'Сторінка тем, що розташовані в порядку популярності. За кількістю розміщених постів, можливість підписки на блоги',
'new_topics' => 'Нові теми',
'new_topics' => 'Нові теми',
'new_topics_info' => 'Нові теми, теми додані останнім часом',
'new_topics_desc' => 'Нові теми додані на сайті останнім часом. Статистика тем та можливість підписатися на теми',
'my_topics' => 'Читаю',
'my_topics_info' => 'Теми, на які я підписаний, читаю',
'my_topics_desc' => 'Теми, які я читаю чи створив',
@ -56,11 +56,11 @@ return [
'deleted_comments_info' => 'Віддалені коментарі...',
'all_answers_info' => 'Усі відповіді...',
'deleted_answers_info' => 'Віддалені відповіді...',
'comments_desc' => 'Усі коментарі, відповіді у порядку черговості у спільноті.',
'domain_desc' => 'Угруповання постів у спільноті за доменом.',
'all_comments' => 'Усі коментарі',
'feed_facet_desc' => 'Загальна стрічка. ',
'feed_facet_posts_desc' => 'Стрічка постів. ',
'feed_facet_questions_desc' => 'Стрічка питань. ',

View file

@ -47,24 +47,29 @@ return [
'code_incorrect' => 'Код неправильний, або він уже використовувався',
'yes_email_pass' => 'Тепер ви можете використовувати свій e-mail та пароль.',
'email_replay' => 'Такий e-mail вже є на сайті',
'email_forbidden' => 'Заборонено реєстрацію із зазначеним e-mail',
'multiple_accounts' => 'Не реєструйте численні облікові записи',
'five_width' => 'Ширина обкладинки менше 500px',
'five_format' => 'Невірний тип файлу',
'silent_mode' => 'Ви не можете публікувати матеріали, ваш обліковий запис перевіряється',
'nick_character' => 'У нікнеймі занадто багато символів, що повторюються',
'nick_exist' => 'Такий нікнейм вже існує',
'check_your_email' => 'Перевірте електронну пошту для активації облікового запису',
'new_email' => 'Щоб активувати email, перевірте пошту',
'user_already' => 'Користувач вже є на сайті',
'invate_replay' => 'Ви вже надіслали запрошення цьому користувачеві',
'invate_limit_stop' => 'Ви вичерпали кількість інвайтів',
'invite_created' => 'Інвайт створено',
'url_reserved' => 'Цей URL блог зарезервований',
'url_correctness' => 'URL не є коректним',
'string_length' => 'Некоректна довжина {name}',
'slug_correctness' => '{name} повинен містити лише латиницю, цифри',
'email_correctness' => 'Неприпустимий e-mail',
'limit_day' => 'Ви вичерпали ліміт на сьогодні',
'content_audit' => 'Ваше повідомлення надіслано на перевірку',
'access_denied' => 'Вам відмовлено у доступі',
'field_limit' => 'Число полів досягло свого максимуму.',
];

Some files were not shown because too many files have changed in this diff Show more