trypost/lang/uk/posts.php

671 lines
41 KiB
PHP
Raw Permalink Normal View History

Add Ukrainian as a supported platform language (#219) * Default AI content language to Ukrainian * Keep English as the default content language * refactor: update content language handling in workspace creation - Changed the default content language in CreateWorkspace to inherit the app's locale instead of defaulting to English. - Updated related tests to reflect this change, ensuring that the content language aligns with the application's current locale settings. - Cleaned up unnecessary code in the BrandTab component for better readability. * Add Ukrainian as a full platform UI locale. Wire uk into languages config with complete lang/uk translations and restore ContentLanguage↔UI parity checks. Co-authored-by: Cursor <cursoragent@cursor.com> * Wire Ukrainian into dayjs and locale coverage tests. Import the uk dayjs locale with Monday week-start and cover uk/uk-UA in brand autofill and SetLocale assertions. Co-authored-by: Cursor <cursoragent@cursor.com> * Harden Ukrainian UI and AI content-language coverage. Cover generator/reviewer/humanizer/image prompts, workspace pickers, persona labels, UI locale switch, and README for uk as a first-class platform language. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Ukrainian Pinterest form strings after main merge. Restore lang/uk posts.php key parity for the new pin title and destination link fields. Co-authored-by: Cursor <cursoragent@cursor.com> * List every supported UI language in the README. Replace the abbreviated multi-language blurb with the full locale set from config. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Paulo Castellano <paulo@castellanos.llc> Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 22:45:30 +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' => 'Duet',
'stitch' => 'Stitch',
'is_aigc' => 'Відео створено за допомогою AI',
'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 Organic.',
'brand_content' => 'Брендований контент',
'brand_content_hint' => 'Ви просуваєте інший бренд або третю сторону. Це відео буде класифіковано як Branded Content.',
'compliance' => [
'agree' => 'Публікуючи, ви погоджуєтеся з',
'music_usage' => 'Підтвердженням використання музики TikTok',
'and' => 'та',
'branded_policy' => 'Політикою брендованого контенту',
],
],
'instagram' => [
'settings' => 'Налаштування Instagram',
'posting_to' => 'Публікація в',
'variant_label' => 'Тип поста',
'variant' => [
'feed' => 'Пост у стрічці',
'reel' => 'Reels',
'story' => 'Stories',
],
'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' => 'Stories',
],
'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' => 'Pin',
'video_pin' => 'Відео-пін',
'carousel' => 'Карусель',
],
'board' => 'дошка',
'select_board' => 'Виберіть дошку',
'no_boards' => 'дошок Pinterest не знайдено. Спочатку створіть дошку у своєму акаунті Pinterest.',
'boards_truncated' => 'Деякі дошки не вдалося завантажити. Якщо вашої немає, відкрийте Pinterest і спробуйте знову.',
'search_board' => 'Пошук досок...',
'no_board_found' => 'Жодна дошка не відповідає вашому пошуку.',
'board_required' => 'Виберіть дошку Pinterest, щоб опублікувати цей пост.',
'title' => 'Заголовок',
'title_placeholder' => 'Необовʼязковий заголовок піна',
'link' => 'Посилання призначення',
'link_placeholder' => 'https://example.com',
'link_invalid' => 'Вкажіть коректне посилання призначення (http або https).',
'title_max' => 'Заголовок не може бути довшим за 100 символів.',
'link_max' => 'Посилання призначення не може бути довшим за 2048 символів.',
],
'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' => 'Згенерувати за допомогою AI',
'title' => 'Згенерувати пост за допомогою AI',
'description' => 'Опишіть, про що має бути пост. AI використає контекст вашого бренду, щоб написати його.',
'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' => 'Не вдалося згенерувати за допомогою AI.',
],
Add Ukrainian as a supported platform language (#219) * Default AI content language to Ukrainian * Keep English as the default content language * refactor: update content language handling in workspace creation - Changed the default content language in CreateWorkspace to inherit the app's locale instead of defaulting to English. - Updated related tests to reflect this change, ensuring that the content language aligns with the application's current locale settings. - Cleaned up unnecessary code in the BrandTab component for better readability. * Add Ukrainian as a full platform UI locale. Wire uk into languages config with complete lang/uk translations and restore ContentLanguage↔UI parity checks. Co-authored-by: Cursor <cursoragent@cursor.com> * Wire Ukrainian into dayjs and locale coverage tests. Import the uk dayjs locale with Monday week-start and cover uk/uk-UA in brand autofill and SetLocale assertions. Co-authored-by: Cursor <cursoragent@cursor.com> * Harden Ukrainian UI and AI content-language coverage. Cover generator/reviewer/humanizer/image prompts, workspace pickers, persona labels, UI locale switch, and README for uk as a first-class platform language. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Ukrainian Pinterest form strings after main merge. Restore lang/uk posts.php key parity for the new pin title and destination link fields. Co-authored-by: Cursor <cursoragent@cursor.com> * List every supported UI language in the README. Replace the abbreviated multi-language blurb with the full locale set from config. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Paulo Castellano <paulo@castellanos.llc> Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 22:45:30 +00:00
],
'review' => [
'button_tooltip' => 'Перевірити за допомогою AI',
'title' => 'Перевірити пост за допомогою AI',
'description' => 'AI перевіряє граматику, орфографію та зрозумілість. Застосовуйте пропозиції, з якими ви погоджуєтеся.',
'loading' => 'Перевіряємо ваш текст...',
'no_issues' => 'Проблем не знайдено. Виглядає добре.',
'original' => 'Оригінал',
'suggestion' => 'Пропозиція',
'apply' => 'Застосувати',
'apply_all' => 'Застосувати все',
'applied' => 'Застосовано',
'cancel' => 'Скасувати',
],
'image_regenerate' => [
'button' => 'Скоригувати',
'title' => 'Скоригувати AI-зображення',
'description' => 'Опишіть правку. Нове зображення замінить поточне та збереже своє місце в каруселі.',
'instruction_label' => 'Інструкція',
'instruction_placeholder' => 'наприклад, Виправити друкарську помилку в заголовку та зробити фон світлішим.',
'processing' => 'Перегенеровуємо зображення... це може зайняти кілька секунд.',
'submit' => 'Перегенерувати зображення',
'cancel' => 'Скасувати',
'success' => 'Зображення оновлено. Нова версія замінила попередню у вашому пості.',
'fallback_title' => 'Покращити текст на цьому зображенні',
'errors' => [
'required' => 'Інструкція обов’язкова.',
'start_failed' => 'Не вдалося розпочати перегенерацію.',
'unavailable' => 'Зараз неможливо перегенерувати це зображення.',
'timeout' => 'Перегенерація триває довше, ніж очікувалося. Спробуйте через мить.',
'media_not_found' => 'Медіафайл не знайдено.',
'not_ai_media' => 'Перегенеровувати можна лише медіа, згенеровані AI.',
],
],
'templates' => [
'image_card' => [
'name' => 'Пост із зображенням',
'description' => 'AI-зображення із заголовком та підписом.',
],
'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' => [
'compose' => 'Написати',
'preview' => 'Попередній перегляд',
'channels' => 'Канали',
'comments' => 'Коментарі',
'comments_empty' => 'Поки що немає коментарів.',
],
'media_picker' => [
'title' => 'Вибрати з галереї',
'search' => 'Пошук медіа...',
'empty' => 'У галереї поки немає медіа',
'cancel' => 'Скасувати',
'add' => 'Додати',
'add_count' => 'Додати :count',
],
'alt_text' => [
'label' => 'Альтернативний текст',
'edit' => 'Редагувати альтернативний текст',
'placeholder' => 'Опишіть це зображення для людей, які використовують програми зчитування з екрана',
'hint' => 'Публікується на платформах, що підтримують описи зображень.',
'save' => 'Зберегти',
],
'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',
'description' => 'Коротке відео до 15 хвилин',
],
'instagram_story' => [
'label' => 'Stories',
'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' => 'Stories',
'description' => 'Вертикальна відеоісторія, до 60 секунд',
],
'tiktok_video' => [
'label' => 'Відео',
'description' => 'Коротке відео',
],
'tiktok_photo' => [
'label' => 'Фотокарусель',
'description' => 'До 35 фото у вигляді каруселі',
],
'youtube_short' => [
'label' => 'Short',
'description' => 'Вертикальне відео до 3 хвилин',
],
'x_post' => [
'label' => 'Пост',
'description' => 'Твіт із текстом та медіа',
],
'threads_post' => [
'label' => 'Пост',
'description' => 'Текстовий пост із необов’язковим медіа',
],
'pinterest_pin' => [
'label' => 'Pin',
'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' => 'Публікація перевищила час очікування. Спробуйте ще раз.',
Add Ukrainian as a supported platform language (#219) * Default AI content language to Ukrainian * Keep English as the default content language * refactor: update content language handling in workspace creation - Changed the default content language in CreateWorkspace to inherit the app's locale instead of defaulting to English. - Updated related tests to reflect this change, ensuring that the content language aligns with the application's current locale settings. - Cleaned up unnecessary code in the BrandTab component for better readability. * Add Ukrainian as a full platform UI locale. Wire uk into languages config with complete lang/uk translations and restore ContentLanguage↔UI parity checks. Co-authored-by: Cursor <cursoragent@cursor.com> * Wire Ukrainian into dayjs and locale coverage tests. Import the uk dayjs locale with Monday week-start and cover uk/uk-UA in brand autofill and SetLocale assertions. Co-authored-by: Cursor <cursoragent@cursor.com> * Harden Ukrainian UI and AI content-language coverage. Cover generator/reviewer/humanizer/image prompts, workspace pickers, persona labels, UI locale switch, and README for uk as a first-class platform language. Co-authored-by: Cursor <cursoragent@cursor.com> * Add Ukrainian Pinterest form strings after main merge. Restore lang/uk posts.php key parity for the new pin title and destination link fields. Co-authored-by: Cursor <cursoragent@cursor.com> * List every supported UI language in the README. Replace the abbreviated multi-language blurb with the full locale set from config. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Paulo Castellano <paulo@castellanos.llc> Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 22:45:30 +00:00
],
'delete' => [
'title' => 'Видалити пост?',
'description' => 'Цю дію не можна скасувати. Пост і все його медіа буде безповоротно видалено.',
'confirm' => 'Так, видалити',
'cancel' => 'Скасувати',
],
'create' => [
'title' => 'Створити новий пост',
'description' => 'Виберіть, з чого хочете почати.',
'scratch_title' => 'Почати з нуля',
'scratch_description' => 'Відкрийте порожній пост і напишіть усе самі.',
'ai_title' => 'Згенерувати за допомогою AI',
'ai_description' => 'Опишіть, що хочете, і AI згенерує вміст за вас.',
'ai_configure_description' => 'Виберіть формат і опишіть пост, який хочете створити.',
'ai_pick_template_description' => 'Виберіть стиль для вашого AI-поста.',
'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' => 'Кількість зображень',
'brand_colors_label' => 'Кольори бренду',
'brand_colors_description' => 'Застосовуйте фірмову палітру вашого workspace до згенерованих зображень. Вимкніть, щоб AI підібрав кольори під вміст.',
'prompt_title' => 'Опишіть свій пост',
'prompt_label' => 'Про що цей пост?',
'prompt_placeholder' => 'наприклад, Оголосити нашу нову функцію каруселі для Instagram',
'preview_error' => 'Щось пішло не так. Спробуйте ще раз.',
'loading_page_title' => 'Генеруємо ваш пост',
'loading_eta' => 'Орієнтовний час: близько :minutes.',
'loading_eta_minute_one' => '1 хвилина',
'loading_eta_minute_other' => ':count хвилин',
'loading_leave_title' => 'Ви можете продовжувати працювати.',
'loading_leave_body' => 'Ми повідомимо вас, коли пост буде готовий.',
'loading_leave_cta' => 'Перейти до календаря',
'loading_create_another_cta' => 'Створити ще один пост',
'loading_tip_credits' => 'Кожне AI-зображення використовує близько 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' => 'Підключіть принаймні один соціальний акаунт, щоб використовувати генерацію AI.',
'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' => 'Pin Pinterest',
'instagram_story' => 'Stories Instagram',
'facebook_story' => 'Stories Facebook',
],
],
],
];