Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
< ? php
return [
'title' => 'Посты' ,
'search' => 'Поиск постов...' ,
'all_posts' => 'В с е посты' ,
'new_post' => 'Новый пост' ,
'no_posts' => 'Посты не найдены' ,
'no_search_results' => 'Нет постов по вашему запросу' ,
'try_different_search' => 'Попробуйте другое ключевое слово или очистите поиск.' ,
'start_creating' => 'Начните с создания первого поста.' ,
'filter_by_label' => 'Фильтр по метке' ,
'label_search_placeholder' => 'Поиск меток...' ,
'no_labels' => 'Метки не найдены.' ,
'clear_label_filter' => 'Сбросить фильтр по метке' ,
'table' => [
'post' => 'Пост' ,
'status' => 'Статус' ,
'content' => 'Содержимое' ,
'platforms' => 'Платформы' ,
'labels' => 'Метки' ,
'scheduled_at' => 'Дата' ,
'actions' => '' ,
],
'manage_posts' => 'Управляйте всеми своими постами' ,
'delete_confirm' => 'Вы уверены, что хотите удалить этот пост?' ,
'by' => 'от' ,
'actions' => [
'view' => 'Открыть пост' ,
'delete' => 'Удалить' ,
'duplicate' => 'Дублировать' ,
'copy_id' => 'Копировать ID' ,
'copied' => 'ID скопирован в буфер обмена' ,
],
'form' => [
'post_type' => 'Тип поста' ,
'board' => 'Доска' ,
'select_board' => 'Выберите доску' ,
'search_board' => 'Поиск доски...' ,
'no_board_found' => 'Доска не найдена' ,
'media' => 'Медиа' ,
'min' => 'Мин' ,
'uploading' => 'Загрузка...' ,
'drop_to_upload' => 'Отпустите для загрузки' ,
'drag_and_drop' => 'Перетащите или нажмите для загрузки' ,
'photos_and_videos' => 'Фото и видео' ,
'photos_only' => 'Только фото' ,
'videos_only' => 'Только видео' ,
'drag_to_reorder' => 'Перетащите для изменения порядка' ,
'caption' => 'Текст' ,
'write_caption' => 'Напишите текст поста...' ,
'content_exceeds_platform' => ':platform: превышение на :over симв. (макс. :limit).' ,
'tiktok' => [
'settings' => 'Настройки TikTok' ,
'variant_label' => 'Тип поста' ,
'variant' => [
'video' => 'Видео' ,
'photo' => 'Фотокарусель' ,
],
'posting_to' => 'Публикация в' ,
'privacy_level' => 'Кто может видеть это видео?' ,
'privacy_placeholder' => 'Выберите, кто может видеть этот пост' ,
'privacy' => [
'public' => 'Доступно всем' ,
'friends' => 'Взаимные подписки' ,
'followers' => 'Подписчики' ,
'private' => 'Только я' ,
'private_disabled_branded' => 'Видимость брендированного контента нельзя установить как «Только я».' ,
],
'privacy_hint' => 'Доступные варианты зависят от настроек вашего аккаунта TikTok.' ,
'auto_add_music' => 'Автоматически добавить музыку' ,
'auto_add_music_hint' => 'Эта функция доступна только для фото. Будет добавлена музыка по умолчанию, которую можно изменить позже.' ,
'yes' => 'Да' ,
'no' => 'Нет' ,
'allow_users' => 'Разрешить пользователям:' ,
'comments' => 'Комментировать' ,
'duet' => 'Дуэт' ,
'stitch' => 'Склейка' ,
'is_aigc' => 'Видео создано с помощью ИИ' ,
'disclose' => 'Раскрыть содержание видео' ,
'disclose_hint' => 'Включите, чтобы указать, что это видео продвигает товары или услуги в обмен на что-то ценное. Ваше видео может продвигать вас, третью сторону или обоих.' ,
'promotional_organic_title' => 'Ваше фото/видео будет отмечено как «Рекламный контент».' ,
'promotional_paid_title' => 'Ваше фото/видео будет отмечено как «Платное партнёрство».' ,
'promotional_description' => 'Это нельзя изменить после публикации видео.' ,
'compliance_incomplete' => 'Необходимо указать, продвигает ли ваш контент вас, третью сторону или обоих.' ,
'privacy_required' => 'При публикации необходимо указать уровень приватности TikTok.' ,
'branded_cleared_private' => 'Настройка приватности сброшена, так как брендированный контент не может быть приватным.' ,
'interaction_disabled_by_creator' => 'Отключено в настройках вашего аккаунта TikTok' ,
'max_duration_exceeded' => 'Видео длится :duration с , но этот аккаунт может публиковать видео длиной не более :max с .' ,
'processing_hint' => 'После публикации может потребоваться несколько минут для обработки контента и е г о появления в вашем профиле TikTok.' ,
'brand_organic' => 'Ваш бренд' ,
'brand_organic_hint' => 'Вы продвигаете себя или собственный бренд. Это видео будет классифицировано как органический контент бренда.' ,
'brand_content' => 'Брендированный контент' ,
'brand_content_hint' => 'Вы продвигаете другой бренд или третью сторону. Это видео будет классифицировано как брендированный контент.' ,
'compliance' => [
'agree' => 'Публикуя, вы соглашаетесь с ' ,
'music_usage' => 'Подтверждением использования музыки TikTok' ,
'and' => 'и' ,
'branded_policy' => 'Политикой в отношении брендированного контента' ,
],
],
'instagram' => [
'settings' => 'Настройки Instagram' ,
'posting_to' => 'Публикация в' ,
'variant_label' => 'Тип поста' ,
'variant' => [
'feed' => 'Пост в ленте' ,
'reel' => 'Reels' ,
'story' => 'История' ,
],
'aspect_label' => 'Соотношение сторон' ,
'aspect' => [
'square' => 'Квадрат (1:1)' ,
'portrait' => 'Портрет (4:5)' ,
'landscape' => 'Альбомная (16:9)' ,
'original' => 'Оригинал' ,
],
],
'facebook' => [
'settings' => 'Настройки Facebook' ,
'posting_to' => 'Публикация в' ,
'variant_label' => 'Тип поста' ,
'variant' => [
'post' => 'Пост' ,
'reel' => 'Reels' ,
'story' => 'История' ,
],
'aspect_label' => 'Соотношение сторон' ,
'aspect' => [
'square' => 'Квадрат (1:1)' ,
'portrait' => 'Портрет (4:5)' ,
'landscape' => 'Альбомная (16:9)' ,
'original' => 'Оригинал' ,
],
],
'linkedin' => [
'settings' => 'Настройки LinkedIn' ,
'settings_page' => 'Настройки страницы LinkedIn' ,
'posting_to' => 'Публикация в' ,
'document_title' => 'Название документа' ,
'document_title_placeholder' => 'Отображается в вашем посте с PDF-документом' ,
],
'pinterest' => [
'settings' => 'Настройки Pinterest' ,
'posting_to' => 'Публикация в' ,
'variant_label' => 'Тип пина' ,
'variant' => [
'pin' => 'Пин' ,
'video_pin' => 'Видео-пин' ,
'carousel' => 'Карусель' ,
],
'board' => 'Доска' ,
'select_board' => 'Выберите доску' ,
'no_boards' => 'Доски Pinterest не найдены. Сначала создайте доску в своём аккаунте Pinterest.' ,
2026-07-25 02:02:40 +00:00
'boards_truncated' => 'Некоторые доски не удалось загрузить. Если вашей нет, откройте Pinterest и попробуйте снова.' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
'search_board' => 'Поиск досок...' ,
'no_board_found' => 'Нет досок по вашему запросу.' ,
'board_required' => 'Выберите доску Pinterest, чтобы опубликовать этот пост.' ,
Add optional Pinterest pin title and destination link (#232)
* Add optional Pinterest pin title, description, and link.
Expose title/description/link across web, API, and MCP; seed description from caption into meta on save, and publish description only from meta.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Expand Pinterest title/description/link test coverage.
Cover web draft persistence and validation bounds, API/MCP update merge and seed, and publisher payload fields on video and carousel pins.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Simplify Pinterest: description is post content again.
Keep optional title and link in meta/settings only. Remove the separate description textarea, seed logic, and meta.description path so Pinterest follows the shared caption pattern.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Refactor Pinterest meta handling and validation.
- Update CreatePost and UpdatePost actions to filter out null values from meta fields.
- Introduce a new method in PinterestPublisher to resolve board IDs, ensuring required fields are validated.
- Enhance PinterestSettings component to manage title and link inputs, including validation for HTTP URLs.
- Update PostPlatformMetaRules to enforce URL validation for Pinterest links.
- Add tests for clearing Pinterest title and link, and for rejecting invalid links during scheduling.
This refactor improves the handling of Pinterest metadata and enhances user experience by ensuring proper validation and error handling.
* Add validation messages and attributes for Pinterest meta fields
- Introduced custom validation messages and friendly attribute names for Pinterest link and title fields in PostPlatformMetaRules.
- Updated StorePostRequest, UpdatePostRequest, and related tools to utilize these new messages and attributes.
- Enhanced tests to assert correct error messages for invalid Pinterest links and title length constraints.
This update improves user feedback during post creation and editing, ensuring clarity in validation errors.
* Remove click.prevent directive from Pinterest link in PinterestPreview component.
This change simplifies the link behavior, allowing default click actions to occur, which may enhance user interaction with the Pinterest link.
* Update validation error messages for Pinterest meta fields in tests
- Refined the assertions in PostApiPlatformMetaTest to include localized validation messages for Pinterest title and link fields.
- Ensured that error messages reflect the updated validation rules, enhancing clarity for users during post creation and editing.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 21:15:50 +00:00
'title' => 'Заголовок' ,
'title_placeholder' => 'Необязательный заголовок пина' ,
'link' => 'Ссылка назначения' ,
'link_placeholder' => 'https://example.com' ,
'link_invalid' => 'Укажите корректную ссылку назначения (http или https).' ,
'title_max' => 'Заголовок не может быть длиннее 100 символов.' ,
'link_max' => 'Ссылка назначения не может быть длиннее 2048 символов.' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
],
'discord' => [
'settings' => 'Настройки Discord' ,
'posting_to' => 'Публикация в' ,
'channel' => 'Канал' ,
'select_channel' => 'Выберите канал' ,
'loading_channels' => 'Загрузка каналов…' ,
'search_channel' => 'Поиск каналов…' ,
'no_channels' => 'Каналы не найдены.' ,
'channel_required' => 'Выберите канал Discord, чтобы опубликовать этот пост.' ,
'mentions' => 'Упоминания' ,
'search_mention' => 'Упомяните роль или участника…' ,
'embeds' => 'Встраивания' ,
'embed' => 'Встраивание' ,
'add_embed' => 'Добавить встраивание' ,
'embed_title' => 'Заголовок встраивания' ,
'embed_description' => 'Описание встраивания' ,
'embed_url' => 'URL встраивания' ,
'embed_image' => 'URL изображения' ,
'embed_color' => 'Цвет' ,
],
'warnings' => [
'no_variant' => 'Выберите тип поста, чтобы продолжить.' ,
'requires_media' => 'Этот тип поста требует хотя бы одно изображение или видео.' ,
'max_files_exceeded' => 'Этот тип поста допускает не более :max медиафайлов (у вас :current).' ,
'min_files_required' => 'Этот тип поста требует не менее :min медиафайлов (у вас :current).' ,
'no_video_allowed' => 'Этот тип поста не принимает видео.' ,
'no_image_allowed' => 'Этот тип поста принимает только видео.' ,
'no_document_allowed' => 'Этот тип поста не принимает PDF-документы.' ,
'no_mixed_media' => 'Изображения и видео нельзя объединять в одном посте.' ,
'document_not_alone' => 'PDF нужно публиковать отдельно, без других изображений или видео.' ,
'gif_not_allowed' => 'Эта платформа не принимает GIF. Удалите GIF или выберите другую сеть.' ,
'image_too_large' => 'Изображение превышает лимит :max для этого типа поста (у вас :current).' ,
'video_too_large' => 'Видео превышает лимит :max для этого типа поста (у вас :current).' ,
'document_too_large' => 'PDF превышает лимит :max для этого типа поста (у вас :current).' ,
'video_too_long' => 'Видео длится :current, но этот тип поста допускает не более :max.' ,
'aspect_ratio_too_narrow' => 'Соотношение сторон :current слишком вытянуто по вертикали для этого типа поста (мин. :min).' ,
'aspect_ratio_too_wide' => 'Соотношение сторон :current слишком широкое для этого типа поста (макс. :max).' ,
],
],
'status' => [
'pending' => 'В ожидании' ,
'draft' => 'Черновик' ,
'scheduled' => 'Запланирован' ,
'publishing' => 'Публикуется' ,
'retrying' => 'Повторная попытка' ,
'published' => 'Опубликован' ,
'partially_published' => 'Частично опубликован' ,
'failed' => 'Ошибка' ,
],
'descriptions' => [
'draft' => 'Посты, ожидающие планирования' ,
'scheduled' => 'Посты, запланированные к публикации' ,
'published' => 'Уже опубликованные посты' ,
],
'ai' => [
'generate' => [
'button_tooltip' => 'Сгенерировать с помощью ИИ' ,
'title' => 'Сгенерировать пост с помощью ИИ' ,
'description' => 'Опишите, о чём должен быть пост. ИИ использует контекст вашего бренда, чтобы написать е г о .' ,
'prompt_label' => 'О чём этот пост?' ,
'prompt_placeholder' => 'например, Анонсировать нашу новую функцию генерации изображений для каруселей' ,
'preview_label' => 'Предпросмотр' ,
'start' => 'Сгенерировать' ,
'apply' => 'Использовать этот контент' ,
'retry' => 'Попробовать снова' ,
'cancel' => 'Отмена' ,
fix: subscribe to AI generation channel before dispatching the job (#269)
* fix: subscribe to AI generation channel before dispatching the job
AiGenerateDialog posted the generate request and only subscribed to the
broadcast channel once the response came back. Reverb's plain Channel
(vendor/laravel/reverb/.../Channels/Channel.php) delivers broadcasts by
iterating the in-memory connection list at send time only — no history,
no replay. If the queued job started streaming text_delta/stream_end
events before the private-channel subscribe handshake finished, those
events were gone for good and the dialog hung on 'streaming' forever.
Generate the generation_id client-side, await channel subscription
confirmation (Echo's channel.subscribed(), backed by
pusher:subscription_succeeded) before sending the generate request, and
have the backend use the client-supplied id instead of minting its own.
Related to #218.
* fix: handle subscribe failure, dialog-close race, and i18n hardcoded strings
Code review on the previous commit surfaced real gaps:
- useAiStream only handled the subscribe-success path (.subscribed()).
A definitive pusher:subscription_error (expired session, CSRF
mismatch) fell through to the 5s timeout and was treated as success,
reproducing the exact #218 hang via a different trigger. subscribe()
now returns a boolean: true on confirm-or-ambiguous-timeout (proceed
optimistically), false only on an explicit error (don't dispatch work
nothing will ever hear).
- AiGenerateDialog now bails without dispatching if the dialog is
closed while awaiting subscription confirmation (up to 5s), and
unsubscribes on a post-subscribe dispatch failure so stale listeners
can't flip status to 'completed' after an error was already shown.
- Extracted aiGenerationChannel() so the frontend has one place to
update if the channel format changes, and cross-referenced the two
remaining backend copies (PostAiGenerateController, StreamPostContent).
- Replaced the two hardcoded English fallback error strings with i18n
keys (posts.ai.generate.errors.*) across all 16 locales — this app
only ships translated copy.
- Simplified subscribe(): dropped a redundant "already settled" guard
and the clearTimeout bookkeeping — Promise.resolve() already no-ops
after the first call, so there was nothing to guard.
* fix: subscribe before dispatch in AI post creation and image regeneration flows
Extracts subscribePrivateChannel as a shared helper and applies the same
subscribe-before-dispatch fix from the post edit flow (issue #218) to the
other two flows that stream over private channels.
Post creation wizard moves the StreamPostCreation dispatch out of
AiPostWizard.vue and into Loading.vue, so the channel is subscribed before
the job that broadcasts on it is dispatched — previously a full page
navigation happened between dispatch and subscribe with no timeout
fallback, so a lost event hung the page forever.
* refactor: trim explanatory comments added in the subscribe-before-dispatch fix
Rationale lives in the commit history, not scattered inline comments.
* refactor: trim remaining explanatory comments from the subscribe-before-dispatch fix
Same cleanup as the previous commit, applied to the files from the
original post-edit-flow fix.
* fix: dedup post-creation dispatch, surface field-level AI errors, harden edge cases
Uses ShouldBeUnique on StreamPostCreation (scoped per-user) instead of an
ad-hoc cache guard, matching the pattern already used by
PublishToSocialPlatform and VerifyUpcomingPostConnections.
Field-level validation errors (prompt/instruction) now render inline via
InputError, matching how every other form in the app surfaces them, instead
of a generic status banner. Also fixes a 422 response missing the `errors`
key that Inertia's client silently swallows, adds error handling around the
wizard's navigation to the loading page, and extracts the duplicated
error-message parsing into a shared helper.
2026-08-10 19:06:37 +00:00
'errors' => [
'start_failed' => 'Н е удалось начать генерацию.' ,
'generation_failed' => 'Н е удалось сгенерировать с помощью ИИ.' ,
],
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
],
'review' => [
'button_tooltip' => 'Проверить с помощью ИИ' ,
'title' => 'Проверить пост с помощью ИИ' ,
'description' => 'ИИ проверяет грамматику, орфографию и ясность. Применяйте предложения, с которыми вы согласны.' ,
'loading' => 'Проверяем ваш текст...' ,
'no_issues' => 'Проблем не найдено. Всё хорошо.' ,
'original' => 'Оригинал' ,
'suggestion' => 'Предложение' ,
'apply' => 'Применить' ,
'apply_all' => 'Применить все' ,
'applied' => 'Применено' ,
'cancel' => 'Отмена' ,
],
'image_regenerate' => [
'button' => 'Скорректировать' ,
'title' => 'Скорректировать ИИ-изображение' ,
'description' => 'Опишите правку. Новое изображение заменит текущее и сохранит своё место в карусели.' ,
'instruction_label' => 'Инструкция' ,
'instruction_placeholder' => 'например, Исправить опечатку в заголовке и сделать фон светлее.' ,
'processing' => 'Пересоздаём изображение... это может занять несколько секунд.' ,
'submit' => 'Пересоздать изображение' ,
'cancel' => 'Отмена' ,
'success' => 'Изображение обновлено. Новая версия заменила предыдущую в вашем посте.' ,
'fallback_title' => 'Улучшить текст на этом изображении' ,
'errors' => [
'required' => 'Инструкция обязательна.' ,
'start_failed' => 'Н е удалось начать пересоздание.' ,
'unavailable' => 'Сейчас невозможно пересоздать это изображение.' ,
'timeout' => 'Пересоздание занимает больше времени, чем ожидалось. Попробуйте через мгновение.' ,
'media_not_found' => 'Медиафайл не найден.' ,
'not_ai_media' => 'Пересоздавать можно только медиа, сгенерированные ИИ.' ,
],
],
'templates' => [
'image_card' => [
'name' => 'Пост с изображением' ,
'description' => 'ИИ-изображение с заголовком и текстом.' ,
],
'carousel' => [
'name' => 'Карусель' ,
'description' => 'Карусель из нескольких слайдов с текстом.' ,
],
'tweet_card' => [
'name' => 'Карточка твита' ,
'description' => 'Ваш пост в стиле публикации X/Twitter.' ,
],
'tweet_card_image' => [
'name' => 'Карточка твита с фото' ,
'description' => 'Ваш пост в виде карточки X/Twitter на размытом фото.' ,
],
],
],
'show' => [
'title' => 'Детали поста' ,
'edit' => 'Изменить' ,
'back' => 'Назад' ,
'no_content' => 'Без текста' ,
'platforms' => 'Платформы' ,
'no_platforms' => 'Платформы не выбраны.' ,
'view_on_platform' => 'Открыть на платформе' ,
'published_on' => 'Опубликовано :date' ,
'scheduled_for' => 'Запланировано на :date' ,
'draft' => 'Черновик' ,
'status_pending' => 'В ожидании' ,
'metrics' => 'Метрики' ,
'metrics_loading' => 'Загрузка метрик…' ,
'metrics_unavailable' => 'Метрики для этой платформы пока недоступны.' ,
'metrics_empty' => 'Метрики отсутствуют.' ,
],
'edit' => [
'title' => 'Изменить пост' ,
'view_title' => 'Просмотр поста' ,
'labels' => 'Метки' ,
'no_labels' => 'Метки ещё не созданы' ,
'schedule' => 'Запланировать' ,
'pick_time' => 'Выберите время' ,
'pick_time_past' => 'Выберите дату и время в будущем.' ,
'post_now' => 'Опубликовать сейчас' ,
'time' => 'Время' ,
'cancel' => 'Отмена' ,
'delete' => 'Удалить' ,
'schedule_for' => 'Запланировать на' ,
'schedule_date' => 'Дата планирования' ,
'unschedule' => 'Отменить планирование' ,
'saving' => 'Сохранение...' ,
'saved' => 'Сохранено' ,
'draft' => 'Черновик' ,
'media' => 'Медиа' ,
'add_media' => 'Добавить медиа' ,
'caption' => 'Текст' ,
'caption_placeholder' => 'Напишите текст поста...' ,
'compose_title' => 'Создать пост' ,
'compose_subtitle' => 'Составьте сообщение и добавьте медиа' ,
'preview_empty' => [
'title' => 'Платформа не выбрана' ,
'description' => 'Выберите платформу для публикации, чтобы увидеть предпросмотр.' ,
],
'drop_zone_title' => 'Добавить медиа' ,
'drop_zone_subtitle' => 'Перетащите файлы или нажмите для выбора' ,
'add' => 'Добавить' ,
'publish_to' => 'Опубликовать в' ,
'organize' => 'Организовать' ,
'signatures' => 'Подписи' ,
'view_on_platform' => 'Открыть на платформе' ,
'platform_status' => 'Статус платформы' ,
'compliance_incomplete' => 'Некоторые настройки платформы не заполнены или несовместимы с прикреплённым медиа.' ,
'compliance' => [
'requires_content_or_media' => 'Добавьте текст или медиа для публикации.' ,
'requires_media' => 'Добавьте изображение или видео для публикации здесь.' ,
'too_many_files' => 'Для этого формата допускается не более :max файлов.' ,
'too_few_files' => 'Добавьте не менее :min файлов для этого формата.' ,
'no_videos' => 'Для этого формата допустимы только изображения.' ,
'no_images' => 'Для этого формата допустимы только видео.' ,
'no_mixed_media' => 'Изображения и видео нельзя объединять в одном посте.' ,
'no_gifs' => 'GIF здесь не поддерживаются.' ,
'no_documents' => 'PDF-документы не поддерживаются этим форматом.' ,
'document_not_alone' => 'PDF нужно публиковать отдельно, без других изображений или видео.' ,
'video_too_large' => 'Видео превышает лимит размера для этой платформы.' ,
'video_too_long' => 'Для этого формата видео должно быть короче :seconds секунд.' ,
'image_too_large' => 'Изображение превышает лимит размера для этой платформы.' ,
'document_too_large' => 'PDF превышает лимит размера для этой платформы.' ,
'aspect_ratio_invalid' => 'Соотношение сторон не поддерживается этим форматом.' ,
'no_content_type' => 'Выберите тип контента для этой платформы.' ,
'requires_text' => 'Добавьте текст — для этого формата нужен заголовок.' ,
],
'publishing' => 'Публикация...' ,
'publishing_overlay_title' => 'Ваш пост публикуется' ,
'publishing_overlay_subtitle' => 'Это может занять несколько мгновений. Вы можете спокойно покинуть эту страницу.' ,
'scheduled_overlay_title' => 'Этот пост запланирован' ,
'scheduled_overlay_subtitle' => 'Запланировано на :date. Сначала отмените планирование, чтобы внести изменения.' ,
'unschedule_cta' => 'Отменить планирование для редактирования' ,
'tabs' => [
2026-07-17 21:38:20 +00:00
'compose' => 'Написать' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
'preview' => 'Предпросмотр' ,
'channels' => 'Каналы' ,
'comments' => 'Комментарии' ,
'comments_empty' => 'Пока нет комментариев.' ,
],
'media_picker' => [
'title' => 'Выбрать из галереи' ,
'search' => 'Поиск медиа...' ,
'empty' => 'В галерее пока нет медиа' ,
'cancel' => 'Отмена' ,
'add' => 'Добавить' ,
'add_count' => 'Добавить :count' ,
],
2026-07-11 12:45:52 +00:00
'alt_text' => [
'label' => 'Альтернативный текст' ,
'edit' => 'Изменить альтернативный текст' ,
'placeholder' => 'Опишите это изображение для людей, использующих программы чтения с экрана' ,
'hint' => 'Публикуется на платформах, поддерживающих описания изображений.' ,
'save' => 'Сохранить' ,
],
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
'emoji_picker' => [
'search' => 'Поиск эмодзи' ,
'empty' => 'Эмодзи не найдены' ,
'recent' => 'Часто используемые' ,
'smileys' => 'Смайлики и эмоции' ,
'people' => 'Люди и тело' ,
'nature' => 'Животные и природа' ,
'food' => 'Еда и напитки' ,
'activities' => 'Активности' ,
'travel' => 'Путешествия и места' ,
'objects' => 'Объекты' ,
'symbols' => 'Символы' ,
'flags' => 'Флаги' ,
],
'status' => [
'pending' => 'В ожидании' ,
'scheduled' => 'Запланирован' ,
'published' => 'Опубликован' ,
'publishing' => 'Публикация...' ,
'retrying' => 'Повторная попытка...' ,
'failed' => 'Ошибка' ,
],
'delete_modal' => [
'title' => 'Удалить пост' ,
'description' => 'Вы уверены, что хотите удалить этот пост? Это действие нельзя отменить.' ,
'action' => 'Удалить' ,
'cancel' => 'Отмена' ,
],
'sync_enable' => [
'title' => 'Включить синхронизацию?' ,
'description' => 'В с е платформы будут использовать одинаковый контент. Любые индивидуальные правки для отдельных платформ будут заменены текущим контентом.' ,
'cancel' => 'Отмена' ,
'action' => 'Включить синхронизацию' ,
],
'sync_disable' => [
'title' => 'Отключить синхронизацию?' ,
'description' => 'Каждая платформа сохранит свой текущий контент, но будущие правки будут применяться только к редактируемой платформе.' ,
'customize_note' => 'Вы сможете настраивать контент для каждой платформы индивидуально.' ,
'cancel' => 'Отмена' ,
'action' => 'Отключить синхронизацию' ,
],
'platforms_dialog' => [
'title' => 'Выберите платформы' ,
'description' => 'Выберите, в какие платформы опубликовать этот пост.' ,
],
'signatures_modal' => [
'search' => 'Поиск подписей...' ,
'no_results' => 'Подписи не найдены.' ,
],
'validation' => [
'select_board' => 'Выберите доску' ,
'images_not_supported' => 'Изображения не поддерживаются' ,
'videos_not_supported' => 'Видео не поддерживаются' ,
'max_images' => 'Н е более :count изображений' ,
'requires_media' => 'Требуется медиа' ,
'requires_content' => 'Требуется текстовое содержимое' ,
'exceeded' => 'превышено на :count' ,
'does_not_support_images' => ':platform не поддерживает изображения' ,
'supports_up_to_images' => ':platform поддерживает до :count изображений' ,
'does_not_support_videos' => ':platform не поддерживает видео' ,
],
],
'content_types' => [
'instagram_feed' => [
'label' => 'Пост в ленте' ,
'description' => 'Появляется в вашей ленте и профиле' ,
],
'instagram_reel' => [
'label' => 'Reels' ,
2026-07-25 00:21:39 +00:00
'description' => 'Короткое видео до 15 минут' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
],
'instagram_story' => [
'label' => 'История' ,
'description' => 'Исчезает через 24 часа' ,
],
'linkedin_post' => [
'label' => 'Пост' ,
'description' => 'Обычный пост — одно изображение, несколько изображений, видео или PDF' ,
],
'linkedin_page_post' => [
'label' => 'Пост' ,
'description' => 'Обычный пост — одно изображение, несколько изображений, видео или PDF' ,
],
'facebook_post' => [
'label' => 'Пост' ,
'description' => 'Обычный пост на вашей странице' ,
],
'facebook_reel' => [
'label' => 'Reels' ,
'description' => 'Короткое видео до 90 секунд' ,
],
'facebook_story' => [
'label' => 'История' ,
'description' => 'Вертикальная видеоистория, до 60 секунд' ,
],
'tiktok_video' => [
'label' => 'Видео' ,
'description' => 'Короткое видео' ,
],
'tiktok_photo' => [
'label' => 'Фотокарусель' ,
'description' => 'До 35 фото в виде листаемой карусели' ,
],
'youtube_short' => [
'label' => 'Short' ,
2026-07-23 15:06:15 +00:00
'description' => 'Вертикальное видео до 3 минут' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
],
'x_post' => [
'label' => 'Пост' ,
'description' => 'Твит с текстом и медиа' ,
],
'threads_post' => [
'label' => 'Пост' ,
'description' => 'Текстовый пост с опциональным медиа' ,
],
'pinterest_pin' => [
'label' => 'Пин' ,
'description' => 'Обычный пин с изображением' ,
],
'pinterest_video_pin' => [
'label' => 'Видео-пин' ,
'description' => 'Видео-пин (4 с – 15 мин)' ,
],
'pinterest_carousel' => [
'label' => 'Карусель' ,
'description' => 'Карусель из нескольких изображений (2– 5 изображений)' ,
],
'bluesky_post' => [
'label' => 'Пост' ,
'description' => 'Текстовый пост с опциональными изображениями' ,
],
'mastodon_post' => [
'label' => 'Пост' ,
'description' => 'Текстовый пост с опциональным медиа' ,
],
'telegram_post' => [
'label' => 'Пост' ,
'description' => 'Текстовый пост с опциональным медиа' ,
],
'discord_message' => [
'label' => 'Сообщение' ,
'description' => 'Сообщение в канал Discord с опциональным медиа и встраиваниями' ,
],
],
'platforms' => [
'linkedin' => 'LinkedIn' ,
'linkedin-page' => 'Страница LinkedIn' ,
'x' => 'X' ,
'tiktok' => 'TikTok' ,
'youtube' => 'YouTube Shorts' ,
'facebook' => 'Страница Facebook' ,
'instagram' => 'Instagram' ,
'threads' => 'Threads' ,
'pinterest' => 'Pinterest' ,
'bluesky' => 'Bluesky' ,
'mastodon' => 'Mastodon' ,
],
'flash' => [
'scheduled' => 'Пост успешно запланирован!' ,
'deleted' => 'Пост успешно удалён!' ,
'duplicated' => 'Пост продублирован как черновик.' ,
'cannot_edit_finalized' => 'Этот пост уже обработан и не может быть опубликован повторно. Продублируйте е г о , чтобы попробовать снова.' ,
'cannot_delete_published' => 'Опубликованные посты нельзя удалить.' ,
'connect_first' => 'Подключите хотя бы одну социальную сеть перед созданием поста.' ,
],
'errors' => [
'account_disconnected' => 'Социальный аккаунт отключён' ,
'account_inactive' => 'Социальный аккаунт деактивирован' ,
'account_token_expired' => 'Сессия социального аккаунта истекла — переподключите' ,
fix: Pinterest video processing timeout — longer poll + retry (#246)
* fix: give Pinterest video processing more time and retry on timeout
A valid ~54s video pin failed after ~90s of polling while Pinterest was
still processing. Extend the poll window to ~5 minutes and treat timeout
as platform unavailable so PublishToSocialPlatform reschedules instead of
failing the post on the first attempt.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: use Laravel Sleep for Pinterest media processing polls
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: inline Pinterest video processing poll constants
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: map Pinterest media upload statuses to an enum
Use the official MediaUploadStatus values (registered, processing,
succeeded, failed) instead of comparing raw strings in the publisher.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: trim Pinterest media processing docblock
* fix: cap platform-unavailable retries and recover stuck retrying posts
Stop infinite reschedules after 6 attempts with a user-safe failure
message, keep technical detail in error_context, recover Retrying
platforms in social:recover-stuck-posts, and drop unused isTerminal().
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: remove unused failedCount in RecoverStuckPosts
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: skip final Pinterest poll sleep and localize recover timeout
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: raise publish job timeout headroom and ignore already-failed platforms
Give social publish jobs 15 minutes so Pinterest media polling fits under
the worker limit, bump Horizon/redis retry_after above that timeout, and
skip handle/failed when the platform is already Failed so delayed jobs
cannot revive posts recovered by social:recover-stuck-posts.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: restore social-publishing and ai-assistant horizon supervisors
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: harden Pinterest 401 handling, unique publish jobs, and recover JSON
Treat media-status 401 as TokenExpired, make PublishToSocialPlatform
unique per platform+attempt so retries still queue, and persist recover
error_context via Eloquent casts instead of manual json_encode.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: mass-update stuck post platforms without per-row each
Eloquent query updates already bind JSON arrays correctly here, so one
UPDATE is enough — no manual json_encode and no N model writes.
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: simplify Pinterest media processing poll loop
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor: simplify publish job retry and terminal status checks
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: do not finalize posts while platforms are still retrying
Co-authored-by: Cursor <cursoragent@cursor.com>
* test: cover Pinterest timeout, unique jobs, and recover edge cases
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: retry Pinterest media poll on connection errors and tighten tests
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: remove ineffective TypeError import that breaks CI
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 23:49:37 +00:00
'platform_unavailable' => 'Платформа временно недоступна. Мы повторим попытку вскоре.' ,
'platform_unavailable_exhausted' => 'Платформа оставалась недоступной после нескольких попыток. Попробуйте позже.' ,
'publishing_timed_out' => 'Публикация превысила время ожидания. Попробуйте снова.' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
],
'delete' => [
'title' => 'Удалить пост?' ,
'description' => 'Это действие нельзя отменить. Пост и все е г о медиа будут безвозвратно удалены.' ,
'confirm' => 'Да, удалить' ,
'cancel' => 'Отмена' ,
],
'create' => [
'title' => 'Создать новый пост' ,
'description' => 'Выберите, с чего хотите начать.' ,
'scratch_title' => 'Начать с нуля' ,
'scratch_description' => 'Откройте пустой пост и напишите всё сами.' ,
'ai_title' => 'Сгенерировать с помощью ИИ' ,
'ai_description' => 'Опишите, что хотите, и ИИ сгенерирует контент за вас.' ,
'ai_configure_description' => 'Выберите формат и опишите пост, который хотите создать.' ,
'ai_pick_template_description' => 'Выберите стиль для вашего ИИ-поста.' ,
'coming_soon' => 'Скоро' ,
'preview' => [
'image_title' => 'Заголовок изображения' ,
'image_body' => 'Текст изображения' ,
],
'steps' => [
'template_picker_title' => 'Выберите стиль' ,
'format_title' => 'Выберите формат' ,
'format_description' => 'Выберите тип поста, который хотите создать.' ,
'account_title' => 'Выберите аккаунт' ,
'account_description' => 'Выберите социальный аккаунт для публикации.' ,
'media_title' => 'Параметры медиа' ,
'media_carousel' => 'Сколько слайдов?' ,
'media_optional' => 'Добавить изображения?' ,
'media_optional_label' => 'Сколько изображений?' ,
'media_none' => 'Нет' ,
'media_count_label' => 'Количество изображений' ,
2026-07-18 18:12:26 +00:00
'brand_colors_label' => 'Цвета бренда' ,
'brand_colors_description' => 'Применяйте фирменную палитру вашего рабочего пространства к создаваемым изображениям. Отключите, чтобы ИИ подобрал цвета под содержание.' ,
Translate the interface into 12 languages
Add full lang/ translations for fr, de, it, nl, pl, el, ja, ko, zh, ru,
tr, and ar — all 23 base files each, with identical key trees to lang/en,
preserved :placeholders and plural forms, and native product terminology.
2026-07-03 18:38:40 +00:00
'prompt_title' => 'Опишите свой пост' ,
'prompt_label' => 'О чём этот пост?' ,
'prompt_placeholder' => 'например, Анонсировать нашу новую функцию карусели для Instagram' ,
'preview_error' => 'Что-то пошло не так. Попробуйте ещё раз.' ,
'loading_page_title' => 'Генерируем ваш пост' ,
'loading_eta' => 'Примерное время: около :minutes.' ,
'loading_eta_minute_one' => 'минуты' ,
'loading_eta_minute_other' => ':count минут' ,
'loading_leave_title' => 'Вы можете продолжать работать.' ,
'loading_leave_body' => 'Мы уведомим вас, когда пост будет готов.' ,
'loading_leave_cta' => 'Перейти в календарь' ,
'loading_create_another_cta' => 'Создать ещё один пост' ,
'loading_tip_credits' => 'Каждое ИИ-изображение расходует около 15 кредитов.' ,
'loading_tip_edit' => 'Вы сможете отредактировать всё, когда пост будет готов.' ,
'loading_tip_draft' => 'Сгенерированные посты попадают в черновики.' ,
'loading_tip_brand' => 'Настройте параметры бренда, чтобы влиять на будущие посты.' ,
'loading_tip_carousel' => 'В карусели создаётся один слайд на каждое загруженное изображение.' ,
'loading_tip_quality' => 'Качество изображений настроено на баланс скорости и стоимости.' ,
'create' => 'Создать пост' ,
'back' => 'Назад' ,
'next' => 'Продолжить' ,
'cancel' => 'Отмена' ,
'discard' => 'Отменить' ,
'retry' => 'Попробовать снова' ,
'no_platforms' => 'Нет подключённых аккаунтов' ,
'connect_first' => 'Подключите хотя бы один социальный аккаунт, чтобы использовать генерацию ИИ.' ,
'no_account_for_template' => 'Подключите совместимый аккаунт, чтобы использовать этот шаблон.' ,
'format' => [
'instagram_feed' => 'Пост в ленте Instagram' ,
'instagram_carousel' => 'Карусель Instagram' ,
'linkedin_post' => 'Пост LinkedIn' ,
'linkedin_page_post' => 'Пост страницы LinkedIn' ,
'x_post' => 'Пост X' ,
'bluesky_post' => 'Пост Bluesky' ,
'threads_post' => 'Пост Threads' ,
'mastodon_post' => 'Пост Mastodon' ,
'telegram_post' => 'Пост Telegram' ,
'discord_message' => 'Сообщение Discord' ,
'facebook_post' => 'Пост Facebook' ,
'pinterest_pin' => 'Пин Pinterest' ,
'instagram_story' => 'История Instagram' ,
'facebook_story' => 'История Facebook' ,
],
],
],
];