diff --git a/app/Http/Controllers/App/PostController.php b/app/Http/Controllers/App/PostController.php index 9b0702eb8..5e9c8a283 100644 --- a/app/Http/Controllers/App/PostController.php +++ b/app/Http/Controllers/App/PostController.php @@ -94,7 +94,10 @@ public function calendar(Request $request): Response|RedirectResponse $this->authorize('view', $workspace); - $tz = 'UTC'; + // Дни календаря считаются в таймзоне воркспейса: пост на 23:00 по + // Брисбену должен лежать в брисбенском дне, а не в UTC-шном. Без + // настройки — прежнее поведение (UTC). + $tz = $workspace->timezone ?: 'UTC'; $view = $request->input('view', 'week'); $currentDay = $request->input('day') diff --git a/app/Http/Requests/App/Workspace/UpdateWorkspaceRequest.php b/app/Http/Requests/App/Workspace/UpdateWorkspaceRequest.php index ad8add4ee..6ba1ae8b3 100644 --- a/app/Http/Requests/App/Workspace/UpdateWorkspaceRequest.php +++ b/app/Http/Requests/App/Workspace/UpdateWorkspaceRequest.php @@ -35,6 +35,8 @@ public function rules(): array 'image_style' => ['sometimes', 'required', 'string', Rule::in(ImageStyle::values())], 'content_language' => ['sometimes', 'string', Rule::in(ContentLanguage::values())], 'logo_url' => ['nullable', 'url', 'max:1024'], + 'timezone' => ['sometimes', 'nullable', 'string', 'timezone:all'], + 'datetime_format' => ['sometimes', 'nullable', 'string', Rule::in(['dmy_24', 'dmy_12', 'dots_24', 'slash_12'])], ]; } } diff --git a/app/Http/Resources/App/HandleInertiaRequests/AuthWorkspaceResource.php b/app/Http/Resources/App/HandleInertiaRequests/AuthWorkspaceResource.php index 4413b15ac..dc3c59333 100644 --- a/app/Http/Resources/App/HandleInertiaRequests/AuthWorkspaceResource.php +++ b/app/Http/Resources/App/HandleInertiaRequests/AuthWorkspaceResource.php @@ -18,6 +18,8 @@ public static function make(Workspace $workspace, ?User $user = null): array 'id' => $workspace->id, 'name' => $workspace->name, 'logo_url' => $workspace->logo_url, + 'timezone' => $workspace->timezone, + 'datetime_format' => $workspace->datetime_format, 'created_at' => $workspace->created_at->toIso8601String(), 'role' => $user ? self::resolveRole($workspace, $user) : null, ]; diff --git a/app/Models/Workspace.php b/app/Models/Workspace.php index aba4944ad..f97c6cc1c 100644 --- a/app/Models/Workspace.php +++ b/app/Models/Workspace.php @@ -33,6 +33,8 @@ class Workspace extends Model 'brand_font', 'image_style', 'content_language', + 'timezone', + 'datetime_format', ]; protected function casts(): array diff --git a/database/migrations/2026_08_20_120000_add_timezone_to_workspaces_table.php b/database/migrations/2026_08_20_120000_add_timezone_to_workspaces_table.php new file mode 100644 index 000000000..f15b8e9ae --- /dev/null +++ b/database/migrations/2026_08_20_120000_add_timezone_to_workspaces_table.php @@ -0,0 +1,26 @@ +string('timezone', 64)->nullable()->after('content_language'); + }); + } + + public function down(): void + { + Schema::table('workspaces', function (Blueprint $table) { + $table->dropColumn('timezone'); + }); + } +}; diff --git a/database/migrations/2026_08_20_140000_add_datetime_format_to_workspaces_table.php b/database/migrations/2026_08_20_140000_add_datetime_format_to_workspaces_table.php new file mode 100644 index 000000000..b07841976 --- /dev/null +++ b/database/migrations/2026_08_20_140000_add_datetime_format_to_workspaces_table.php @@ -0,0 +1,26 @@ +string('datetime_format', 20)->nullable()->after('timezone'); + }); + } + + public function down(): void + { + Schema::table('workspaces', function (Blueprint $table) { + $table->dropColumn('datetime_format'); + }); + } +}; diff --git a/lang/ar/settings.php b/lang/ar/settings.php index d3dc72c88..9921e761f 100644 --- a/lang/ar/settings.php +++ b/lang/ar/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'إدارة أعضاء مساحة العمل والدعوات', 'name' => 'الاسم', 'name_placeholder' => 'مساحة عملي', + 'timezone' => 'المنطقة الزمنية', + 'timezone_auto' => 'تلقائي — منطقة المتصفح (:tz)', + 'timezone_description' => 'يُعرض التقويم والجدولة وتواريخ المنشورات بهذه المنطقة الزمنية لجميع أعضاء مساحة العمل.', + 'datetime_format' => 'تنسيق التاريخ والوقت', + 'datetime_format_auto' => 'تلقائي — حسب اللغة', + 'datetime_format_description' => 'يُطبَّق على التقويم وجميع قوائم المنشورات.', 'save' => 'حفظ', 'danger_description' => 'إجراءات لا يمكن التراجع عنها.', 'delete_warning' => 'تحذير', diff --git a/lang/de/settings.php b/lang/de/settings.php index e1bfc9991..1b2424f72 100644 --- a/lang/de/settings.php +++ b/lang/de/settings.php @@ -142,6 +142,12 @@ 'members_description' => 'Verwalte die Mitglieder und Einladungen des Workspace', 'name' => 'Name', 'name_placeholder' => 'Mein Workspace', + 'timezone' => 'Zeitzone', + 'timezone_auto' => 'Auto — Browser-Zeitzone (:tz)', + 'timezone_description' => 'Kalender, Zeitplan und Beitragsdaten werden für alle im Workspace in dieser Zeitzone angezeigt.', + 'datetime_format' => 'Datums- & Zeitformat', + 'datetime_format_auto' => 'Auto — Sprachstandard', + 'datetime_format_description' => 'Gilt für den Kalender und alle Beitragslisten.', 'save' => 'Speichern', 'danger_description' => 'Unwiderrufliche Aktionen.', 'delete_warning' => 'Warnung', diff --git a/lang/el/settings.php b/lang/el/settings.php index 3ce5941f8..6dc9400cb 100644 --- a/lang/el/settings.php +++ b/lang/el/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Διαχειριστείτε τα μέλη και τις προσκλήσεις του workspace', 'name' => 'Όνομα', 'name_placeholder' => 'Το workspace μου', + 'timezone' => 'Ζώνη ώρας', + 'timezone_auto' => 'Αυτόματα — ζώνη του προγράμματος περιήγησης (:tz)', + 'timezone_description' => 'Το ημερολόγιο, ο προγραμματισμός και οι ημερομηνίες αναρτήσεων εμφανίζονται σε αυτήν τη ζώνη για όλο το workspace.', + 'datetime_format' => 'Μορφή ημερομηνίας και ώρας', + 'datetime_format_auto' => 'Αυτόματα — προεπιλογή γλώσσας', + 'datetime_format_description' => 'Εφαρμόζεται στο ημερολόγιο και σε όλες τις λίστες αναρτήσεων.', 'save' => 'Αποθήκευση', 'danger_description' => 'Μη αναστρέψιμες ενέργειες.', 'delete_warning' => 'Προειδοποίηση', diff --git a/lang/en/settings.php b/lang/en/settings.php index b4b7dc806..79feff6ec 100644 --- a/lang/en/settings.php +++ b/lang/en/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Manage workspace members and invitations', 'name' => 'Name', 'name_placeholder' => 'My Workspace', + 'timezone' => 'Timezone', + 'timezone_auto' => 'Auto — browser timezone (:tz)', + 'timezone_description' => 'Calendar, schedule and post dates are shown in this timezone for everyone in the workspace.', + 'datetime_format' => 'Date & time format', + 'datetime_format_auto' => 'Auto — language default', + 'datetime_format_description' => 'Applied to the calendar and all post lists.', 'save' => 'Save', 'danger_description' => 'Irreversible actions.', 'delete_warning' => 'Warning', diff --git a/lang/es/settings.php b/lang/es/settings.php index 44310f2b3..def7ac3a0 100644 --- a/lang/es/settings.php +++ b/lang/es/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Administra miembros e invitaciones del workspace', 'name' => 'Nombre', 'name_placeholder' => 'Mi Workspace', + 'timezone' => 'Zona horaria', + 'timezone_auto' => 'Auto — zona del navegador (:tz)', + 'timezone_description' => 'El calendario, la programación y las fechas de publicaciones se muestran en esta zona para todo el workspace.', + 'datetime_format' => 'Formato de fecha y hora', + 'datetime_format_auto' => 'Auto — según el idioma', + 'datetime_format_description' => 'Se aplica al calendario y a todas las listas de publicaciones.', 'save' => 'Guardar', 'danger_description' => 'Acciones irreversibles.', 'delete_warning' => 'Advertencia', diff --git a/lang/fr/settings.php b/lang/fr/settings.php index 2cede7c15..c31c80f10 100644 --- a/lang/fr/settings.php +++ b/lang/fr/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Gérez les membres et les invitations de l\'espace de travail', 'name' => 'Nom', 'name_placeholder' => 'Mon espace de travail', + 'timezone' => 'Fuseau horaire', + 'timezone_auto' => 'Auto — fuseau du navigateur (:tz)', + 'timezone_description' => 'Le calendrier, la planification et les dates des publications s’affichent dans ce fuseau pour tout le workspace.', + 'datetime_format' => 'Format de date et d’heure', + 'datetime_format_auto' => 'Auto — selon la langue', + 'datetime_format_description' => 'Appliqué au calendrier et à toutes les listes de publications.', 'save' => 'Enregistrer', 'danger_description' => 'Actions irréversibles.', 'delete_warning' => 'Avertissement', diff --git a/lang/it/settings.php b/lang/it/settings.php index 08f8e3417..e06b1bd03 100644 --- a/lang/it/settings.php +++ b/lang/it/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Gestisci i membri e gli inviti del workspace', 'name' => 'Nome', 'name_placeholder' => 'Il mio workspace', + 'timezone' => 'Fuso orario', + 'timezone_auto' => 'Auto — fuso del browser (:tz)', + 'timezone_description' => 'Calendario, programmazione e date dei post vengono mostrati in questo fuso per tutto il workspace.', + 'datetime_format' => 'Formato data e ora', + 'datetime_format_auto' => 'Auto — in base alla lingua', + 'datetime_format_description' => 'Applicato al calendario e a tutti gli elenchi di post.', 'save' => 'Salva', 'danger_description' => 'Azioni irreversibili.', 'delete_warning' => 'Attenzione', diff --git a/lang/ja/settings.php b/lang/ja/settings.php index 94e76beb7..ab9b01105 100644 --- a/lang/ja/settings.php +++ b/lang/ja/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'ワークスペースのメンバーと招待を管理します', 'name' => '名前', 'name_placeholder' => 'マイワークスペース', + 'timezone' => 'タイムゾーン', + 'timezone_auto' => '自動 — ブラウザのタイムゾーン (:tz)', + 'timezone_description' => 'カレンダー、スケジュール、投稿日時はワークスペース全員にこのタイムゾーンで表示されます。', + 'datetime_format' => '日付と時刻の形式', + 'datetime_format_auto' => '自動 — 言語の既定', + 'datetime_format_description' => 'カレンダーとすべての投稿リストに適用されます。', 'save' => '保存', 'danger_description' => '元に戻せない操作です。', 'delete_warning' => '警告', diff --git a/lang/ko/settings.php b/lang/ko/settings.php index 77fb6569b..45def7382 100644 --- a/lang/ko/settings.php +++ b/lang/ko/settings.php @@ -140,6 +140,12 @@ 'members_description' => '워크스페이스 멤버와 초대를 관리하세요', 'name' => '이름', 'name_placeholder' => '내 워크스페이스', + 'timezone' => '시간대', + 'timezone_auto' => '자동 — 브라우저 시간대 (:tz)', + 'timezone_description' => '캘린더, 일정, 게시물 날짜가 워크스페이스 전체에 이 시간대로 표시됩니다.', + 'datetime_format' => '날짜 및 시간 형식', + 'datetime_format_auto' => '자동 — 언어 기본값', + 'datetime_format_description' => '캘린더와 모든 게시물 목록에 적용됩니다.', 'save' => '저장', 'danger_description' => '되돌릴 수 없는 작업입니다.', 'delete_warning' => '경고', diff --git a/lang/nl/settings.php b/lang/nl/settings.php index 46c1eb79d..70c922abb 100644 --- a/lang/nl/settings.php +++ b/lang/nl/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Beheer workspaceleden en uitnodigingen', 'name' => 'Naam', 'name_placeholder' => 'Mijn workspace', + 'timezone' => 'Tijdzone', + 'timezone_auto' => 'Auto — browsertijdzone (:tz)', + 'timezone_description' => 'Kalender, planning en berichtdatums worden voor iedereen in de workspace in deze tijdzone getoond.', + 'datetime_format' => 'Datum- en tijdnotatie', + 'datetime_format_auto' => 'Auto — taalstandaard', + 'datetime_format_description' => 'Toegepast op de kalender en alle berichtlijsten.', 'save' => 'Opslaan', 'danger_description' => 'Onomkeerbare acties.', 'delete_warning' => 'Waarschuwing', diff --git a/lang/pl/settings.php b/lang/pl/settings.php index 89520348f..ab126c024 100644 --- a/lang/pl/settings.php +++ b/lang/pl/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Zarządzaj członkami i zaproszeniami przestrzeni roboczej', 'name' => 'Nazwa', 'name_placeholder' => 'Moja przestrzeń robocza', + 'timezone' => 'Strefa czasowa', + 'timezone_auto' => 'Auto — strefa przeglądarki (:tz)', + 'timezone_description' => 'Kalendarz, harmonogram i daty postów są pokazywane w tej strefie wszystkim w workspace.', + 'datetime_format' => 'Format daty i godziny', + 'datetime_format_auto' => 'Auto — wg języka', + 'datetime_format_description' => 'Stosowany do kalendarza i wszystkich list postów.', 'save' => 'Zapisz', 'danger_description' => 'Nieodwracalne działania.', 'delete_warning' => 'Ostrzeżenie', diff --git a/lang/pt-BR/settings.php b/lang/pt-BR/settings.php index 1ec2a7936..1fea9a65a 100644 --- a/lang/pt-BR/settings.php +++ b/lang/pt-BR/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Gerencie membros e convites do workspace', 'name' => 'Nome', 'name_placeholder' => 'Meu Workspace', + 'timezone' => 'Fuso horário', + 'timezone_auto' => 'Auto — fuso do navegador (:tz)', + 'timezone_description' => 'Calendário, agendamento e datas das publicações são exibidos neste fuso para todo o workspace.', + 'datetime_format' => 'Formato de data e hora', + 'datetime_format_auto' => 'Auto — padrão do idioma', + 'datetime_format_description' => 'Aplicado ao calendário e a todas as listas de publicações.', 'save' => 'Salvar', 'danger_description' => 'Ações irreversíveis.', 'delete_warning' => 'Atenção', diff --git a/lang/ru/settings.php b/lang/ru/settings.php index 79cf9d15f..398db12fa 100644 --- a/lang/ru/settings.php +++ b/lang/ru/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Управляйте участниками и приглашениями рабочего пространства', 'name' => 'Название', 'name_placeholder' => 'Моё рабочее пространство', + 'timezone' => 'Часовой пояс', + 'timezone_auto' => 'Авто — часовой пояс браузера (:tz)', + 'timezone_description' => 'Календарь, расписание и даты постов показываются в этом поясе всем участникам воркспейса.', + 'datetime_format' => 'Формат даты и времени', + 'datetime_format_auto' => 'Авто — по языку интерфейса', + 'datetime_format_description' => 'Применяется к календарю и всем спискам постов.', 'save' => 'Сохранить', 'danger_description' => 'Необратимые действия.', 'delete_warning' => 'Внимание', diff --git a/lang/tr/settings.php b/lang/tr/settings.php index f2852da05..20b42c50c 100644 --- a/lang/tr/settings.php +++ b/lang/tr/settings.php @@ -142,6 +142,12 @@ 'members_description' => 'Çalışma alanı üyelerini ve davetlerini yönetin', 'name' => 'Ad', 'name_placeholder' => 'Çalışma Alanım', + 'timezone' => 'Saat dilimi', + 'timezone_auto' => 'Otomatik — tarayıcı saat dilimi (:tz)', + 'timezone_description' => 'Takvim, plan ve gönderi tarihleri çalışma alanındaki herkese bu dilimde gösterilir.', + 'datetime_format' => 'Tarih ve saat biçimi', + 'datetime_format_auto' => 'Otomatik — dil varsayılanı', + 'datetime_format_description' => 'Takvime ve tüm gönderi listelerine uygulanır.', 'save' => 'Kaydet', 'danger_description' => 'Geri alınamaz işlemler.', 'delete_warning' => 'Uyarı', diff --git a/lang/uk/settings.php b/lang/uk/settings.php index b53ab183b..3d7511f83 100644 --- a/lang/uk/settings.php +++ b/lang/uk/settings.php @@ -140,6 +140,12 @@ 'members_description' => 'Керуйте учасниками та запрошеннями робочого простору', 'name' => 'Назва', 'name_placeholder' => 'Мій робочий простір', + 'timezone' => 'Часовий пояс', + 'timezone_auto' => 'Авто — часовий пояс браузера (:tz)', + 'timezone_description' => 'Календар, розклад і дати постів показуються в цьому поясі всім учасникам воркспейсу.', + 'datetime_format' => 'Формат дати й часу', + 'datetime_format_auto' => 'Авто — за мовою інтерфейсу', + 'datetime_format_description' => 'Застосовується до календаря та всіх списків постів.', 'save' => 'Зберегти', 'danger_description' => 'Незворотні дії.', 'delete_warning' => 'Увага', diff --git a/lang/zh/settings.php b/lang/zh/settings.php index e830106c5..236cd3ddc 100644 --- a/lang/zh/settings.php +++ b/lang/zh/settings.php @@ -140,6 +140,12 @@ 'members_description' => '管理工作区成员和邀请', 'name' => '名称', 'name_placeholder' => '我的工作区', + 'timezone' => '时区', + 'timezone_auto' => '自动 — 浏览器时区 (:tz)', + 'timezone_description' => '日历、排期和帖子日期将以此时区向工作区所有成员显示。', + 'datetime_format' => '日期和时间格式', + 'datetime_format_auto' => '自动 — 随界面语言', + 'datetime_format_description' => '应用于日历和所有帖子列表。', 'save' => '保存', 'danger_description' => '不可撤销的操作。', 'delete_warning' => '警告', diff --git a/resources/js/components/settings/WorkspaceTab.vue b/resources/js/components/settings/WorkspaceTab.vue index 100fdc5c1..aa30457ad 100644 --- a/resources/js/components/settings/WorkspaceTab.vue +++ b/resources/js/components/settings/WorkspaceTab.vue @@ -18,6 +18,8 @@ interface Workspace { name: string; has_logo: boolean; logo_url: string | null; + timezone?: string | null; + datetime_format?: string | null; } defineProps<{ @@ -27,6 +29,23 @@ defineProps<{ }>(); const { canManageBilling } = useWorkspaceRole(); + +const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + +const timezones: string[] = (() => { + try { + return (Intl as any).supportedValuesOf('timeZone') as string[]; + } catch { + return [browserTimezone]; + } +})(); + +const formatPresets = [ + { value: 'dmy_24', example: '20 Aug 2026, 18:30' }, + { value: 'dmy_12', example: '20 Aug 2026, 6:30 PM' }, + { value: 'dots_24', example: '20.08.2026 18:30' }, + { value: 'slash_12', example: '08/20/2026 6:30 PM' }, +];