diff --git a/.github/workflows/build-binary-for-release.yml b/.github/workflows/build-binary-for-release.yml index 2bce67142..76f1c9530 100644 --- a/.github/workflows/build-binary-for-release.yml +++ b/.github/workflows/build-binary-for-release.yml @@ -36,7 +36,7 @@ jobs: - name: Set up Node uses: actions/setup-node@v4 with: - node-version: 20.18.1 + node-version: 20.19.0 - name: Node Build run: make install-ui-packages ui diff --git a/.gitignore b/.gitignore index ba66f51a0..d5aed0da5 100644 --- a/.gitignore +++ b/.gitignore @@ -17,10 +17,8 @@ /go.work* /logs /ui/node_modules -/ui/build/*/*/* -/ui/build/*.json -/ui/build/*.html -/ui/build/*.txt +/ui/build/* +!/ui/build/favicon.ico /vendor Thumbs*.db tmp diff --git a/Makefile b/Makefile index 0623e1efd..74e51886b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: build clean ui -VERSION=2.0.2 +VERSION=2.0.3 BIN=answer DIR_SRC=./cmd/answer DOCKER_CMD=docker diff --git a/README.md b/README.md index cf257aba2..0d958e007 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ To learn more about the project, visit [answer.apache.org](https://answer.apache ### Running with docker ```bash -docker run -d -p 9080:80 -v answer-data:/data --name answer apache/answer:2.0.2 +docker run -d -p 9080:80 -v answer-data:/data --name answer apache/answer:2.0.3 ``` For more information, see [Installation](https://answer.apache.org/docs/installation). @@ -40,7 +40,7 @@ You can also check out the [plugins here](https://answer.apache.org/plugins). ### Prerequisites -- Golang >= 1.23 +- Golang >= 1.25 - Node.js >= 20 - pnpm >= 9 - [mockgen](https://github.com/uber-go/mock?tab=readme-ov-file#installation) >= 0.6.0 diff --git a/charts/templates/deployment.yaml b/charts/templates/deployment.yaml index f1b9d1862..57d57ac29 100644 --- a/charts/templates/deployment.yaml +++ b/charts/templates/deployment.yaml @@ -101,7 +101,7 @@ spec: - name: data {{- if .Values.persistence.enabled }} persistentVolumeClaim: - claimName: {{ include "answer.fullname" . }}-claim + claimName: {{ .Values.persistence.existingClaim | default (printf "%s-claim" (include "answer.fullname" .)) }} {{- else }} emptyDir: {} {{- end -}} diff --git a/charts/templates/pvc.yaml b/charts/templates/pvc.yaml index 640fb9fe0..e01ff820f 100644 --- a/charts/templates/pvc.yaml +++ b/charts/templates/pvc.yaml @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -{{ if .Values.persistence.enabled -}} +{{ if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}} kind: PersistentVolumeClaim apiVersion: v1 metadata: diff --git a/charts/values.yaml b/charts/values.yaml index d932db848..7a5c16f3b 100644 --- a/charts/values.yaml +++ b/charts/values.yaml @@ -91,6 +91,8 @@ persistence: accessMode: ReadWriteOnce size: 5Gi annotations: {} + # Use an existing PVC instead of creating one; when set, no PVC is created by this chart + existingClaim: "" # To restore a PVC from a VolumeSnapshot, set the dataSource; # the kind and apiGroup are optional and default to the shown values dataSource: {} diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 446f6cc0b..66e162784 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -274,7 +274,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database, permissionController := controller.NewPermissionController(rankService) userPluginController := controller.NewUserPluginController(pluginCommonService) reviewController := controller.NewReviewController(reviewService, rankService, captchaService) - metaService := meta2.NewMetaService(metaCommonService, userCommon, answerRepo, questionRepo, eventqueueService) + metaService := meta2.NewMetaService(metaCommonService, userCommon, answerRepo, questionRepo, objService, eventqueueService) metaController := controller.NewMetaController(metaService) badgeGroupRepo := badge_group.NewBadgeGroupRepo(dataData, uniqueIDRepo) eventRuleRepo := badge.NewEventRuleRepo(dataData) diff --git a/go.mod b/go.mod index 5787c8b18..7b68c180c 100644 --- a/go.mod +++ b/go.mod @@ -64,6 +64,7 @@ require ( go.uber.org/mock v0.6.0 golang.org/x/crypto v0.53.0 golang.org/x/image v0.20.0 + golang.org/x/net v0.56.0 golang.org/x/term v0.44.0 golang.org/x/text v0.39.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df @@ -170,7 +171,6 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.10.0 // indirect golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect - golang.org/x/net v0.56.0 // indirect golang.org/x/sys v0.46.0 // indirect golang.org/x/tools v0.47.0 // indirect google.golang.org/protobuf v1.34.2 // indirect diff --git a/i18n/de_DE.yaml b/i18n/de_DE.yaml index 151341c60..90a88ff0f 100644 --- a/i18n/de_DE.yaml +++ b/i18n/de_DE.yaml @@ -71,7 +71,7 @@ backend: user: other: Standard ohne speziellen Zugriff. admin: - other: Habe die volle Berechtigung, auf die Seite zuzugreifen. + other: Hat die volle Berechtigung, auf die Seite zuzugreifen. moderator: other: Hat Zugriff auf alle Beiträge außer Admin-Einstellungen. privilege: @@ -266,7 +266,7 @@ backend: cannot_set_synonym_as_itself: other: Du kannst das Synonym des aktuellen Tags nicht als sich selbst festlegen. minimum_count: - other: Not enough tags were entered. + other: Nicht genügend Tags angegeben. smtp: config_from_name_cannot_be_email: other: Der Absendername kann keine E-Mail-Adresse sein. @@ -311,13 +311,13 @@ backend: add_bulk_users_amount_error: other: "Die Anzahl der Benutzer, die du auf einmal hinzufügst, sollte im Bereich von 1-{{.MaxAmount}} liegen." status_suspended_forever: - other: "This user was suspended forever. This user doesn't meet a community guideline." + other: "Dieser Benutzer wurde dauerhaft gesperrt. Dieser Benutzer verstößt gegen eine Community-Richtlinie." status_suspended_until: - other: "This user was suspended until {{.SuspendedUntil}}. This user doesn't meet a community guideline." + other: "Dieser Benutzer wird bis {{.SuspendedUntil}} gesperrt. Dieser Benutzer verstößt gegen eine Community-Richtlinie." status_deleted: - other: "This user was deleted." + other: "Dieser Benutzer wurde gelösch." status_inactive: - other: "This user is inactive." + other: "Dieser Benutzer ist inaktiv." config: read_config_failed: other: Lesekonfiguration fehlgeschlagen @@ -456,7 +456,7 @@ backend: comment_answer: other: kommentierte Antwort reply_to_you: - other: hat Ihnen geantwortet + other: hat dir geantwortet mention_you: other: hat dich erwähnt your_question_is_closed: @@ -598,7 +598,7 @@ backend: name: other: Kommentator desc: - other: Hinterlassen Sie 5 Kommentare. + other: Hinterlasse 5 Kommentare. new_user_of_the_month: name: other: Neuer Benutzer des Monats @@ -606,14 +606,14 @@ backend: other: Ausstehende Beiträge in ihrem ersten Monat. read_guidelines: name: - other: Lesen Sie die Richtlinien + other: Lese die Richtlinien desc: - other: Lesen Sie die [Community-Richtlinien]. + other: Lese die [Community-Richtlinien]. reader: name: other: Leser desc: - other: Lesen Sie alle Antworten in einem Thema mit mehr als 10 Antworten. + other: Lese alle Antworten in einem Thema mit mehr als 10 Antworten. welcome: name: other: Willkommen @@ -761,7 +761,7 @@ backend: other: Fragen mit 25 oder mehr Punkten. great_question: name: - other: Große Frage + other: Großartige Frage desc: other: Frage mit 50 oder mehr Punkten. popular_question: @@ -809,7 +809,16 @@ ui: how_to_format: title: Wie man formatiert desc: >- -
einen Beitrag erwähnen: #post_id
um Links
<https://url.com>
[Titel](https://url.com)Zwischen den Absätzen Zeilenumbrüche einfügen
_italic_ oder **fett**
Code um 4 Leerzeichen einrücken
Zitat durch Setzen von > am Anfang der Zeile
Backtick-Escapes `wie _this_`
Codeumrandungen mit Backticks `
`
Code hier
``Einen Beitrag erwähnen: #post_id
Links einfügen:
<https://url.com>
[Titel](https://url.com)Zwischen den Absätzen Zeilenumbrüche einfügen
_kursiv_ oder **fett**
Code um 4 Leerzeichen einrücken
Zitat durch Setzen von > am Anfang der Zeile
Backtick-Escapes `wie _dies_`
Codeumrandungen mit Backticks `
```
Code hier
```Wir erlauben es nicht, Tags mit Beiträgenzu löschen.
Bitte entfernen Sie dieses Tag zuerst aus den Beiträgen.
+Wir erlauben es nicht, Tags mit Beiträgenzu löschen.
Bitte entferne dieses Tag zuerst aus den Beiträgen.
tip_with_synonyms: >- -Wir erlauben nicht Tags mit Synonymenzu löschen.
Bitte entfernen Sie zuerst die Synonyme von diesem Schlagwort.
+Wir erlauben nicht Tags mit Synonymenzu löschen.
Bitte entferne zuerst die Synonyme von diesem Schlagwort.
tip: Bist du sicher, dass du löschen möchtest? close: Schließen merge: @@ -1076,12 +1085,12 @@ ui: x_minutes_ago: "Vor {{count}}m" x_hours_ago: "Vor {{count}}h" hour: Stunde - day: tag + day: Tag hours: Stunden days: Tage - month: month - months: months - year: year + month: Monat + months: Monate + year: Jahr reaction: heart: Herz smile: Lächeln @@ -1137,10 +1146,10 @@ ui: more: Mehr wiki: Wiki ask: - title: Create Question + title: Frage erstellen edit_title: Frage bearbeiten default_reason: Frage bearbeiten - default_first_reason: Create question + default_first_reason: Frage erstellen similar_questions: Ähnliche Fragen form: fields: @@ -1148,17 +1157,17 @@ ui: label: Version title: label: Titel - placeholder: What's your topic? Be specific. + placeholder: Was ist das Thema? msg: empty: Der Titel darf nicht leer sein. range: Titel bis zu 150 Zeichen body: - label: Körper + label: Inhalt msg: - empty: Körper darf nicht leer sein. + empty: Inhalt darf nicht leer sein. hint: - optional_body: Describe what the question is about. - minimum_characters: "Describe what the question is about, at least {{min_content_length}} characters are required." + optional_body: Beschreibe worum es in der Frage geht. + minimum_characters: "Erläutere mit wenigstens {{min_content_length}} Zeichen, worum es in der Frage geht." tags: label: Stichworte msg: @@ -1179,9 +1188,9 @@ ui: add_btn: Schlagwort hinzufügen create_btn: Neuen Tag erstellen search_tag: Tag suchen - hint: Describe what your content is about, at least one tag is required. - hint_zero_tags: Describe what your content is about. - hint_more_than_one_tag: "Describe what your content is about, at least {{min_tags_number}} tags are required." + hint: Beschreibe den Inhalt. Mindestens ein Tag ist erforderlich. + hint_zero_tags: Beschreibe den Inhalt. + hint_more_than_one_tag: "Beschreibe mit mindestens {{min_tags_number}} Tags, worum es bei diesem Thema geht." no_result: Keine Tags gefunden tag_required_text: Benötigter Tag (mindestens eins) header: @@ -1233,7 +1242,7 @@ ui: msg: empty: Der Name darf nicht leer sein. range: Der Name muss zwischen 2 und 30 Zeichen lang sein. - character: 'Must use the character set "a-z", "0-9", " - . _"' + character: 'Erlaubte Zeichen sind "a-z", "0-9", " - . _"' email: label: E-Mail msg: @@ -1253,7 +1262,7 @@ ui: msg: empty: E-Mail darf nicht leer sein. change_email: - btn_cancel: Stornieren + btn_cancel: Abbrechen btn_update: E-Mail Adresse aktualisieren send_success: >- Wenn ein Konto mit {{mail}} übereinstimmt, solltest du in Kürze eine E-Mail mit Anweisungen erhalten, wie du dein Passwort zurücksetzen kannst. @@ -1311,7 +1320,7 @@ ui: caption: Leute können dich als "@Benutzername" erwähnen. msg: Benutzername darf nicht leer sein. msg_range: Der Benutzername muss zwischen 2 und 30 Zeichen lang sein. - character: 'Must use the character set "a-z", "0-9", "- . _"' + character: 'Erlaubte Zeichen sind "a-z", "0-9", "- . _"' avatar: label: Profilbild gravatar: Gravatar @@ -1389,9 +1398,9 @@ ui: title: Related answers: antworten linked_question: - title: Linked - description: Posts linked to - no_linked_question: No contents linked from this content. + title: Verlinkt + description: Beitrag verlinkt nach + no_linked_question: Zu diesem Inhalt sind keine Links vorhanden. invite_to_answer: title: Frage jemanden desc: Lade Leute ein, von denen du glaubst, dass sie die Antwort wissen könnten. @@ -1400,7 +1409,7 @@ ui: search: Personen suchen question_detail: action: Aktion - created: Created + created: Erstellt Asked: Gefragt asked: gefragt update: Geändert @@ -1451,11 +1460,11 @@ ui: list: confirm_btn: Liste title: Diesen Beitrag auflisten - content: Möchten Sie diesen Beitrag wirklich in der Liste anzeigen? + content: Möchtest du diesen Beitrag wirklich in der Liste anzeigen? unlist: confirm_btn: Von Liste nehmen title: Diesen Beitrag von der Liste nehmen - content: Möchten Sie diesen Beitrag wirklich aus der Liste ausblenden? + content: Möchtest du diesen Beitrag wirklich aus der Liste ausblenden? pin: title: Diesen Beitrag anpinnen content: Bist du sicher, dass du den Beitrag global anheften möchtest? Dieser Beitrag wird in allen Beitragslisten ganz oben erscheinen. @@ -1533,7 +1542,7 @@ ui: follow: Folgen following: Folgend counts: "{{count}} Ergebnisse" - counts_loading: "... Results" + counts_loading: "... Ergebnisse" more: Mehr sort_btns: relevance: Relevanz @@ -1562,12 +1571,12 @@ ui: title: Fehler... delete_permanently: title: Endgültig löschen - content: Sind Sie sicher, dass Sie den Inhalt endgültig löschen möchten? + content: Bist du sicher, dass du den Inhalt endgültig löschen möchtest? account_result: success: Dein neues Konto ist bestätigt; du wirst zur Startseite weitergeleitet. link: Weiter zur Startseite oops: Hoppla! - invalid: Der Link, den Sie verwendet haben, funktioniert nicht mehr. + invalid: Der verwendete Link funktioniert nicht mehr. confirm_new_email: Deine E-Mail wurde aktualisiert. confirm_new_email_invalid: >- Dieser Bestätigungslink ist leider nicht mehr gültig. Vielleicht wurde deine E-Mail-Adresse bereits geändert? @@ -1710,13 +1719,13 @@ ui: empty: Kontakt-E-Mail kann nicht leer sein. incorrect: Falsches Format der Kontakt-E-Mail. login_required: - label: Privat + label: Privater Bereich switch: Anmeldung erforderlich text: Nur eingeloggte Benutzer können auf diese Community zugreifen. admin_name: label: Name msg: Der Name darf nicht leer sein. - character: 'Must use the character set "a-z", "0-9", " - . _"' + character: 'Erlaubte Zeichen sind "a-z", "0-9", " - . _"' msg_max_length: Der Name muss zwischen 2 und 30 Zeichen lang sein. admin_password: label: Passwort @@ -1727,7 +1736,7 @@ ui: msg_max_length: Das Passwort darf maximal 32 Zeichen lang sein. admin_confirm_password: label: "Passwort bestätigen" - text: "Bitte geben Sie Ihr Passwort erneut ein, um es zu bestätigen." + text: "Bitte gib dein Passwort erneut ein, um es zu bestätigen." msg: "Passwortbestätigung stimmt nicht überein!" admin_email: label: E-Mail @@ -1777,7 +1786,7 @@ ui: branding: Branding legal: Rechtliches write: Schreiben - terms: Terms + terms: Nutzungsbedingungen tos: Nutzungsbedingungen privacy: Privatsphäre seo: SEO @@ -1789,16 +1798,16 @@ ui: installed_plugins: Installierte Plugins apperance: Erscheinungsbild community: Community - advanced: Advanced + advanced: Erweitert tags: Tags - rules: Rules - policies: Policies - security: Security - files: Files - apikeys: API Keys - intelligence: Intelligence - ai_assistant: AI Assistant - ai_settings: AI Settings + rules: Regeln + policies: Richtlinien + security: Sicherheit + files: Dateien + apikeys: API-Schlüssel + intelligence: Intelligenz + ai_assistant: KI-Assistent + ai_settings: KI-Einstellungen mcp: MCP website_welcome: Willkommen auf {{site_name}} user_center: @@ -1808,7 +1817,7 @@ ui: badges: modal: title: Glückwunsch - content: Sie haben sich ein neues Abzeichen verdient. + content: Du hast dir ein neues Abzeichen verdient. close: Schließen confirm: Abzeichen ansehen title: Abzeichen @@ -1833,7 +1842,7 @@ ui: users: "Nutzer:" flags: "Meldungen:" reviews: "Rezension:" - site_health: Gesundheit der Website + site_health: Status der Website version: "Version:" https: "HTTPS:" upload_folder: "Hochladeverzeichnis:" @@ -1914,7 +1923,7 @@ ui: form: fields: users: - label: Masse Benutzer hinzufügen + label: Mehrere Benutzer hinzufügen placeholder: "John Smith, john@example.com, BUSYopr2\nAlice, alice@example.com, fpDntV8q" text: Trenne "Name, E-Mail, Passwort" mit Kommas. Ein Benutzer pro Zeile. msg: "Bitte gib die E-Mail des Nutzers ein, eine pro Zeile." @@ -1937,7 +1946,7 @@ ui: created_at: Angelegt am delete_at: Löschzeit suspend_at: Sperrzeit - suspend_until: Suspend until + suspend_until: Gesperrt bis status: Status role: Rolle action: Aktion @@ -1972,8 +1981,8 @@ ui: suspend_user: title: Diesen Benutzer sperren content: Ein gesperrter Benutzer kann sich nicht einloggen. - label: How long will the user be suspended for? - forever: Forever + label: Wie lang soll dieser Benutzer gesperrt sein? + forever: Für immer questions: page_title: Fragen unlisted: Nicht gelistet @@ -2035,11 +2044,11 @@ ui: msg: Die Zeitzone darf nicht leer sein. text: Wähle eine Stadt in der gleichen Zeitzone wie du. avatar: - label: Default avatar - text: For users without a custom avatar of their own. + label: Standard-Avatar + text: Für Nutzer, die keinen eigenen Avatar haben. gravatar_base_url: - label: Gravatar base URL - text: URL of the Gravatar provider's API base. Ignored when empty. + label: Gravatar Basis-URL + text: URL zur API des Gravatar-Anbieters. Wird ignoriert, wenn leer. smtp: page_title: SMTP from_email: @@ -2111,17 +2120,17 @@ ui: always_display: Externen Inhalt immer anzeigen ask_before_display: Vor der Anzeige externer Inhalte fragen write: - page_title: Files + page_title: Dateien min_content: - label: Minimum question body length - text: Minimum allowed question body length in characters. + label: Minimale Länge für den Inhalt einer Frage + text: Minimale Anzahl an Zeichen für den Inhalt einer Frage. restrict_answer: title: Antwort bearbeiten label: Jeder Benutzer kann für jede Frage nur eine Antwort schreiben - text: "Schalten Sie aus, um es Benutzern zu ermöglichen, mehrere Antworten auf dieselbe Frage zu schreiben, was dazu führen kann, dass Antworten nicht im Fokus stehen." + text: "Schalte es aus, um es Benutzern zu ermöglichen, mehrere Antworten auf dieselbe Frage zu schreiben, was dazu führen kann, dass Antworten nicht im Fokus stehen." min_tags: - label: "Minimum tags per question" - text: "Minimum number of tags required in a question." + label: "Minimum an Tags pro Frage" + text: "Benötigte minimale Anzahl an Tags pro Frage." recommend_tags: label: Empfohlene Tags text: "Empfohlene Tags werden standardmäßig in der Dropdown-Liste angezeigt." @@ -2141,14 +2150,14 @@ ui: label: Maximale Anhanggröße (MB) text: "Die maximale Dateigröße für Dateianhänge." image_megapixels: - label: Max. BildmePixel - text: "Maximale Anzahl an Megapixeln für ein Bild." + label: Max. Megapixel pro Bild + text: "Maximale Anzahl an Megapixel für ein Bild." image_extensions: - label: Autorisierte Bilderweiterungen - text: "Eine Liste von Dateierweiterungen, die für die Anzeige von Bildern erlaubt sind, getrennt durch Kommata." + label: Erlaubte Bilderweiterungen + text: "Eine Liste von Dateierweiterungen, die für die Anzeige von Bildern erlaubt sind, getrennt durch Kommas." attachment_extensions: - label: Autorisierte Anhänge Erweiterungen - text: "Eine Liste von Dateierweiterungen, die für das Hochladen erlaubt sind, getrennt mit Kommas. WARNUNG: Erlaubt Uploads kann Sicherheitsprobleme verursachen." + label: Erlaubte Anhänge Erweiterungen + text: "Eine Liste von Dateierweiterungen, die für das Hochladen erlaubt sind, getrennt mit Kommas. WARNUNG: Der Erlaubten von Uploads kann Sicherheitsprobleme verursachen." seo: page_title: SEO permalink: @@ -2168,28 +2177,25 @@ ui: label: Hintergrundstil der Navigationsleiste primary_color: label: Primäre Farbe - text: Ändere die Farben, die von deinen Themes verwendet werden + text: Ändere die Farben, die von deinen Themen verwendet werden layout: label: Layout - full_width: Full-width - fixed_width: Fixed-width + full_width: Volle Breite + fixed_width: Feste Breite css_and_html: page_title: CSS und HTML custom_css: - label: Benutzerdefinierte CSS - text: > - + label: Benutzerdefiniertes CSS + text: Dies wird als <link> eingefügt. head: - label: Kopf - text: > - + label: Head + text: Dies wird vor </head> eingefügt. header: label: Header - text: > - + text: Dies wird nach <body> eingefügt. footer: label: Fusszeile - text: Dies wird vor