Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitea/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ jobs:
NEXT_PUBLIC_APP_URL=https://${{ env.DOMAIN }}
APP_API_URL=http://${{ env.INNER_DOMAIN }}.app.svc.cluster.local/api/v2
APP_API_PROXY=http://${{ env.INNER_DOMAIN }}.app.svc.cluster.local/api/v2
NEXT_PUBLIC_BUILD_ID=${{ env.ENV }}.${{ steps.vars.outputs.sha_short }}

- name: Set up kubeconfig
# uses: azure/k8s-set-context@v4
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Data fetching uses SWR with global config: 2s deduping, no focus revalidation, r
NEXT_PUBLIC_APP_URL # Client-side app URL
APP_API_URL # Server-side API base URL
APP_API_PROXY # API proxy destination (used in next.config.ts rewrites)
NEXT_PUBLIC_BUILD_ID # Build identifier (CI sets <env>.<short sha>); sent with frontend error reports
```

Frontend proxies API calls via Next.js rewrites: `/api/v2/:path*` → `APP_API_PROXY/:path*`. `next.config.ts` also sets global security headers (`X-Content-Type-Options`, `Referrer-Policy`, `X-Frame-Options: SAMEORIGIN`), immutable long-cache headers for `/assets` and `/monaco`, and `optimizePackageImports` for `antd` / `@ant-design/*` / `@iconify/react`. `pnpm` is pinned via `packageManager` (`pnpm@10.x`); use it rather than npm/yarn.
Expand Down
5 changes: 4 additions & 1 deletion deploy/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ FROM base AS builder
ARG NEXT_PUBLIC_APP_URL=https://scriptcat.org
ARG APP_API_PROXY=https://scriptcat.org/api/v2
ARG APP_API_URL=https://scriptcat.org/api/v2
# 前端构建版本,随错误上报写进日志,用来把压缩后的堆栈对回某次构建
ARG NEXT_PUBLIC_BUILD_ID=""

# 设置工作目录
WORKDIR /app

ENV NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} \
APP_API_URL=${APP_API_URL} \
APP_API_PROXY=${APP_API_PROXY}
APP_API_PROXY=${APP_API_PROXY} \
NEXT_PUBLIC_BUILD_ID=${NEXT_PUBLIC_BUILD_ID}

# 从 deps 阶段复制 node_modules
COPY --from=deps /app/node_modules ./node_modules
Expand Down
94 changes: 93 additions & 1 deletion public/locales/de-DE/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@
"save_button": "Speichern",
"save_success": "Erfolgreich gespeichert",
"title": "Systemkonfiguration",
"turnstile_enabled": "Verifizierung aktivieren",
"turnstile_enabled_extra": "Wenn deaktiviert, entfällt die Menschen-Verifizierung bei Anmeldung, Registrierung und Passwort-Zurücksetzung",
"turnstile_site_key": "Website-Schlüssel (Site Key)",
"turnstile_secret_key": "Geheimer Schlüssel",
"turnstile_title": "Cloudflare Turnstile",
Expand Down Expand Up @@ -669,7 +671,48 @@
"col_createtime": "Created at",
"col_actions": "Actions",
"action_view": "View",
"filter_status": "Filter by status"
"filter_status": "Filter by status",
"tab_script": "Skriptmeldungen",
"tab_content": "Inhaltsmeldungen",
"content": {
"status_all": "Alle",
"status_1": "Offen",
"status_2": "Bearbeitet",
"status_3": "Abgelehnt",
"type_all": "Alle Typen",
"type_score": "Bewertung",
"type_issue": "Feedback",
"type_issue_comment": "Feedback-Antwort",
"col_type": "Typ",
"col_summary": "Gemeldeter Inhalt",
"col_author": "Autor",
"col_times": "Anzahl",
"target_deleted": "(Inhalt gelöscht)",
"action_handle": "Bearbeiten",
"drawer_title": "Inhaltsmeldung #{id}",
"view_origin": "Am Originalort ansehen",
"published_at": "Veröffentlicht {time}",
"handler": "Bearbeitet von",
"handle_note": "Notiz",
"no_note": "(keine)",
"result_deleted": "Inhalt gelöscht",
"result_resolved": "Bearbeitet",
"result_rejected": "Abgelehnt",
"snapshot": "Gemeldeter Inhalt",
"records": "Meldungen ({count})",
"load_failed": "Laden fehlgeschlagen",
"retry": "Erneut versuchen",
"action_reject": "Ablehnen",
"action_resolve": "Als bearbeitet markieren",
"action_delete": "Inhalt löschen und abschließen",
"action_reopen": "Wieder öffnen",
"delete_confirm_title": "Diesen Inhalt löschen?",
"delete_confirm_desc": "Der Inhalt wird endgültig gelöscht und alle offenen Meldungen dazu werden abgeschlossen.",
"note_hint": "Nur für Admins sichtbar",
"note_placeholder": "Bearbeitungsnotiz (optional)",
"action_success": "Erledigt",
"action_failed": "Aktion fehlgeschlagen, bitte erneut versuchen"
}
}
},
"auth": {
Expand Down Expand Up @@ -812,6 +855,54 @@
"loading_editor": "Editor wird geladen...",
"placeholder": "Bitte Inhalt eingeben...",
"uploading_image": "Bild wird hochgeladen..."
},
"contentReport": {
"title_score": "Bewertung melden",
"title_issue": "Feedback melden",
"title_issue_comment": "Feedback-Antwort melden",
"quote_score": "Bewertung von {name}",
"quote_issue": "Feedback von {name}: „{title}“",
"quote_issue_comment": "Antwort von {name}",
"reason_label": "Meldegrund",
"reasons": {
"spam": {
"name": "Spam / Werbung",
"desc": "Eigenwerbung, Traffic-Lenkung, Flooding"
},
"abuse": {
"name": "Beleidigung",
"desc": "Persönliche Angriffe, Diskriminierung, Belästigung"
},
"porn": {
"name": "Pornografisch / vulgär",
"desc": "Sexuelle, gewalttätige oder verstörende Inhalte"
},
"illegal": {
"name": "Rechtswidrig",
"desc": "Illegale Inhalte, Betrug, schädliche Links"
},
"misleading": {
"name": "Manipulierte Bewertung / Falschinfo",
"desc": "Ohne Bezug zum Skript, gefälschte Bewertungen"
},
"other": {
"name": "Sonstiges",
"desc": "Bitte in der Anmerkung erläutern"
}
},
"note_label": "Zusätzliche Angaben",
"note_optional": "(optional)",
"note_required_mark": "(erforderlich)",
"note_placeholder": "Beschreibe das Problem",
"note_required_error": "Bei „Sonstiges“ bitte eine Erläuterung angeben",
"note_too_long_error": "Die Angaben dürfen höchstens 500 Zeichen lang sein",
"privacy": "Meldungen sind nur für Administratoren sichtbar. Die gemeldete Person erfährt nicht, wer gemeldet hat.",
"submit": "Meldung absenden",
"cancel": "Abbrechen",
"success": "Meldung gesendet. Danke, dass du die Community unterstützt.",
"duplicate": "Du hast diesen Inhalt bereits gemeldet. Die Administratoren kümmern sich bald darum.",
"not_found": "Der Inhalt existiert nicht oder wurde gelöscht",
"submit_failed": "Meldung konnte nicht gesendet werden, bitte später erneut versuchen"
}
},
"error": {
Expand Down Expand Up @@ -2455,6 +2546,7 @@
"ban_clean_options": "Cleanup options",
"ban_clean_scores": "Remove user ratings",
"ban_clean_scripts": "Remove user scripts",
"ban_clean_issues": "Feedback und Antworten des Nutzers entfernen",
"ban_success": "User banned",
"unban_success": "User unbanned",
"ban_confirm_title": "Confirm ban",
Expand Down
94 changes: 93 additions & 1 deletion public/locales/en-US/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,8 @@
"save_button": "Save",
"save_success": "Saved successfully",
"title": "System Configuration",
"turnstile_enabled": "Enable verification",
"turnstile_enabled_extra": "When off, login, registration and password reset skip the human verification",
"turnstile_site_key": "Site Key",
"turnstile_secret_key": "Secret Key",
"turnstile_title": "Cloudflare Turnstile",
Expand Down Expand Up @@ -669,7 +671,48 @@
"col_createtime": "Created at",
"col_actions": "Actions",
"action_view": "View",
"filter_status": "Filter by status"
"filter_status": "Filter by status",
"tab_script": "Script reports",
"tab_content": "Content reports",
"content": {
"status_all": "All",
"status_1": "Pending",
"status_2": "Resolved",
"status_3": "Rejected",
"type_all": "All types",
"type_score": "Review",
"type_issue": "Feedback",
"type_issue_comment": "Feedback reply",
"col_type": "Type",
"col_summary": "Reported content",
"col_author": "Author",
"col_times": "Count",
"target_deleted": "(Content deleted)",
"action_handle": "Handle",
"drawer_title": "Content report #{id}",
"view_origin": "View in place",
"published_at": "Posted {time}",
"handler": "Handled by",
"handle_note": "Note",
"no_note": "(none)",
"result_deleted": "Content deleted",
"result_resolved": "Resolved",
"result_rejected": "Rejected",
"snapshot": "Reported content",
"records": "Reports ({count})",
"load_failed": "Failed to load",
"retry": "Retry",
"action_reject": "Reject",
"action_resolve": "Mark as resolved",
"action_delete": "Delete content and close",
"action_reopen": "Reopen",
"delete_confirm_title": "Delete this content?",
"delete_confirm_desc": "The content will be permanently deleted and all pending reports on it will be closed.",
"note_hint": "Visible to admins only",
"note_placeholder": "Handling note (optional)",
"action_success": "Done",
"action_failed": "Action failed, please try again"
}
}
},
"auth": {
Expand Down Expand Up @@ -812,6 +855,54 @@
"loading_editor": "Loading editor...",
"placeholder": "Please enter content...",
"uploading_image": "Uploading image..."
},
"contentReport": {
"title_score": "Report review",
"title_issue": "Report feedback",
"title_issue_comment": "Report feedback reply",
"quote_score": "Review by {name}",
"quote_issue": "Feedback by {name}: \"{title}\"",
"quote_issue_comment": "Reply by {name}",
"reason_label": "Reason",
"reasons": {
"spam": {
"name": "Spam / ads",
"desc": "Promotion, traffic diversion, flooding"
},
"abuse": {
"name": "Abuse",
"desc": "Personal attacks, discrimination, harassment"
},
"porn": {
"name": "Pornographic / vulgar",
"desc": "Sexual, violent or disturbing content"
},
"illegal": {
"name": "Illegal",
"desc": "Illegal info, scams, malicious links"
},
"misleading": {
"name": "Fake ratings / misleading",
"desc": "Unrelated to the script, fake reviews"
},
"other": {
"name": "Other",
"desc": "Please explain in the note"
}
},
"note_label": "Additional details",
"note_optional": "(optional)",
"note_required_mark": "(required)",
"note_placeholder": "Describe the problem",
"note_required_error": "Please provide details when choosing \"Other\"",
"note_too_long_error": "Details cannot exceed 500 characters",
"privacy": "Reports are only visible to administrators. The reported user will not know who reported them.",
"submit": "Submit report",
"cancel": "Cancel",
"success": "Report submitted. Thank you for helping keep the community healthy.",
"duplicate": "You have already reported this content. Administrators will handle it soon.",
"not_found": "The content does not exist or has been deleted",
"submit_failed": "Failed to submit the report, please try again later"
}
},
"error": {
Expand Down Expand Up @@ -2463,6 +2554,7 @@
"ban_clean_options": "Cleanup options",
"ban_clean_scores": "Remove user ratings",
"ban_clean_scripts": "Remove user scripts",
"ban_clean_issues": "Remove user feedback and replies",
"ban_success": "User banned",
"unban_success": "User unbanned",
"ban_confirm_title": "Confirm ban",
Expand Down
94 changes: 93 additions & 1 deletion public/locales/ja-JP/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,8 @@
"save_button": "保存",
"save_success": "保存しました",
"title": "システム設定",
"turnstile_enabled": "人間確認を有効化",
"turnstile_enabled_extra": "オフにすると、ログイン・登録・パスワード再設定で人間確認を行いません",
"turnstile_site_key": "サイトキー",
"turnstile_secret_key": "シークレットキー",
"turnstile_title": "Cloudflare Turnstile",
Expand Down Expand Up @@ -669,7 +671,48 @@
"col_createtime": "Created at",
"col_actions": "Actions",
"action_view": "View",
"filter_status": "Filter by status"
"filter_status": "Filter by status",
"tab_script": "スクリプトの通報",
"tab_content": "コンテンツの通報",
"content": {
"status_all": "すべて",
"status_1": "未処理",
"status_2": "処理済み",
"status_3": "却下",
"type_all": "すべての種類",
"type_score": "レビュー",
"type_issue": "フィードバック",
"type_issue_comment": "フィードバックへの返信",
"col_type": "種類",
"col_summary": "通報されたコンテンツ",
"col_author": "投稿者",
"col_times": "件数",
"target_deleted": "(コンテンツは削除されました)",
"action_handle": "対応",
"drawer_title": "コンテンツ通報 #{id}",
"view_origin": "元の場所で表示",
"published_at": "投稿日時 {time}",
"handler": "対応者",
"handle_note": "対応メモ",
"no_note": "(記入なし)",
"result_deleted": "コンテンツ削除済み",
"result_resolved": "処理済み",
"result_rejected": "却下",
"snapshot": "通報されたコンテンツ",
"records": "通報履歴({count})",
"load_failed": "読み込みに失敗しました",
"retry": "再試行",
"action_reject": "却下",
"action_resolve": "対応済みにする",
"action_delete": "コンテンツを削除して完了",
"action_reopen": "再オープン",
"delete_confirm_title": "このコンテンツを削除しますか?",
"delete_confirm_desc": "コンテンツは完全に削除され、このコンテンツに対する未処理の通報はすべて完了になります。",
"note_hint": "管理者のみ表示",
"note_placeholder": "対応メモ(任意)",
"action_success": "操作が完了しました",
"action_failed": "操作に失敗しました。もう一度お試しください"
}
}
},
"auth": {
Expand Down Expand Up @@ -812,6 +855,54 @@
"loading_editor": "エディターを読み込み中...",
"placeholder": "内容を入力してください...",
"uploading_image": "画像をアップロード中..."
},
"contentReport": {
"title_score": "レビューを通報",
"title_issue": "フィードバックを通報",
"title_issue_comment": "フィードバックへの返信を通報",
"quote_score": "{name} さんのレビュー",
"quote_issue": "{name} さんのフィードバック「{title}」",
"quote_issue_comment": "{name} さんの返信",
"reason_label": "通報の理由",
"reasons": {
"spam": {
"name": "スパム・広告",
"desc": "誘導、宣伝、連投"
},
"abuse": {
"name": "誹謗中傷",
"desc": "個人攻撃、差別、嫌がらせ"
},
"porn": {
"name": "性的・低俗",
"desc": "性的・暴力的・不快な内容"
},
"illegal": {
"name": "違法・規約違反",
"desc": "違法情報、詐欺、悪意のあるリンク"
},
"misleading": {
"name": "不正評価・虚偽内容",
"desc": "スクリプトと無関係、偽のレビュー"
},
"other": {
"name": "その他",
"desc": "補足説明に記入してください"
}
},
"note_label": "補足説明",
"note_optional": "(任意)",
"note_required_mark": "(必須)",
"note_placeholder": "問題の内容を記入してください",
"note_required_error": "「その他」を選んだ場合は説明を記入してください",
"note_too_long_error": "補足説明は 500 文字以内で入力してください",
"privacy": "通報内容は管理者のみに表示され、通報された人には誰が通報したか分かりません。",
"submit": "通報する",
"cancel": "キャンセル",
"success": "通報を送信しました。コミュニティへのご協力ありがとうございます。",
"duplicate": "このコンテンツはすでに通報済みです。管理者が対応しますのでお待ちください。",
"not_found": "コンテンツが存在しないか、削除されています",
"submit_failed": "通報の送信に失敗しました。しばらくしてからもう一度お試しください"
}
},
"error": {
Expand Down Expand Up @@ -2455,6 +2546,7 @@
"ban_clean_options": "Cleanup options",
"ban_clean_scores": "Remove user ratings",
"ban_clean_scripts": "Remove user scripts",
"ban_clean_issues": "ユーザーのフィードバックと返信を削除",
"ban_success": "User banned",
"unban_success": "User unbanned",
"ban_confirm_title": "Confirm ban",
Expand Down
Loading
Loading