mirror of https://gitee.com/answerdev/answer.git
Merge branch 'dev' into feat/ui-1.1.0
This commit is contained in:
commit
f37218bc70
|
@ -15,7 +15,7 @@ builds:
|
||||||
- id: build
|
- id: build
|
||||||
main: ./cmd/answer/.
|
main: ./cmd/answer/.
|
||||||
binary: answer
|
binary: answer
|
||||||
ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser
|
ldflags: -s -w -X github.com/answerdev/answer/cmd.Version={{.Version}} -X github.com/answerdev/answer/cmd.Revision={{.ShortCommit}} -X github.com/answerdev/answer/cmd.Time={{.Date}} -X main.BuildUser=goreleaser
|
||||||
flags: -v
|
flags: -v
|
||||||
goos:
|
goos:
|
||||||
- linux
|
- linux
|
||||||
|
@ -26,7 +26,7 @@ builds:
|
||||||
- id: build-windows
|
- id: build-windows
|
||||||
main: ./cmd/answer/.
|
main: ./cmd/answer/.
|
||||||
binary: answer
|
binary: answer
|
||||||
ldflags: -s -w -X main.Version={{.Version}} -X main.Revision={{.ShortCommit}} -X main.Time={{.Date}} -X main.BuildUser=goreleaser
|
ldflags: -s -w -X github.com/answerdev/answer/cmd.Version={{.Version}} -X github.com/answerdev/answer/cmd.Revision={{.ShortCommit}} -X github.com/answerdev/answer/cmd.Time={{.Date}} -X main.BuildUser=goreleaser
|
||||||
flags: -v
|
flags: -v
|
||||||
goos:
|
goos:
|
||||||
- windows
|
- windows
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
||||||
.PHONY: build clean ui
|
.PHONY: build clean ui
|
||||||
|
|
||||||
VERSION=1.0.7
|
VERSION=1.0.8
|
||||||
BIN=answer
|
BIN=answer
|
||||||
DIR_SRC=./cmd/answer
|
DIR_SRC=./cmd/answer
|
||||||
DOCKER_CMD=docker
|
DOCKER_CMD=docker
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching, relative path matching, and
|
||||||
|
# negation (prefixed with !). Only one pattern per line.
|
||||||
|
.DS_Store
|
||||||
|
# Common VCS dirs
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.bzr/
|
||||||
|
.bzrignore
|
||||||
|
.hg/
|
||||||
|
.hgignore
|
||||||
|
.svn/
|
||||||
|
# Common backup files
|
||||||
|
*.swp
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
# Various IDEs
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
*.tmproj
|
||||||
|
.vscode/
|
|
@ -1,6 +1,6 @@
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: answer
|
name: answer
|
||||||
description: a simple answer deployments for kubernetes
|
description: A simple answer deployments for kubernetes
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
appVersion: "0.1.0"
|
appVersion: "1.0.7"
|
|
@ -1,2 +1,75 @@
|
||||||
# Helm Charts for Answer project
|
# answer
|
||||||
|
|
||||||
|
An open-source knowledge-based community software. You can use it quickly to build Q&A community for your products, customers, teams, and more.
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes 1.20+
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The following table lists the configurable parameters of the answer chart and their default values.
|
||||||
|
|
||||||
|
| Parameter | Description | Default |
|
||||||
|
| --------- | ----------- | ------- |
|
||||||
|
| `replicaCount` | Number of answer replicas | `1` |
|
||||||
|
| `image.repository` | Image repository | `answerdev/answer` |
|
||||||
|
| `image.pullPolicy` | Image pull policy | `Always` |
|
||||||
|
| `image.tag` | Image tag | `latest` |
|
||||||
|
| `env` | Optional environment variables for answer | `LOG_LEVEL: INFO` |
|
||||||
|
| `extraContainers` | Optional sidecar containers to run along side answer | `[]` |
|
||||||
|
| `persistence.enabled` | Enable or disable persistence for the /data volume | `true` |
|
||||||
|
| `persistence.accessMode` | Specify the access mode of the persistent volume | `ReadWriteOnce` |
|
||||||
|
| `persistence.size` | The size of the persistent volume | `5Gi` |
|
||||||
|
| `persistence.annotations` | Annotations to add to the volume claim | `{}` |
|
||||||
|
| `imagePullSecrets` | Reference to one or more secrets to be used when pulling images | `[]` |
|
||||||
|
| `nameOverride` | nameOverride replaces the name of the chart in the Chart.yaml file, when this is used to construct Kubernetes object names. | |
|
||||||
|
| `fullnameOverride` | fullnameOverride completely replaces the generated name. | |
|
||||||
|
| `serviceAccount.create` | If `true`, create a new service account | `true` |
|
||||||
|
| `serviceAccount.annotations` | Annotations to add to the service account | `{}` |
|
||||||
|
| `serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the fullname template | |
|
||||||
|
| `podAnnotations` | Annotations to add to the answer pod | `{}` |
|
||||||
|
| `podSecurityContext` | Security context for the answer pod | `{}` refer to [Default Security Contexts](#default-security-contexts) |
|
||||||
|
| `securityContext` | Security context for the answer container | `{}` refer to [Default Security Contexts](#default-security-contexts) |
|
||||||
|
| `service.type` | The type of service to be used | `ClusterIP` |
|
||||||
|
| `service.port` | The port that the service should listen on for requests. Also used as the container port. | `80` |
|
||||||
|
| `ingress.enabled` | Enable or disable ingress. | `false` |
|
||||||
|
| `resources` | CPU/memory resource requests/limits | `{}` |
|
||||||
|
| `autoscaling.enabled` | Enable or disable pod autoscaling. If enabled, replicas are disabled. | `false` |
|
||||||
|
| `nodeSelector` | Node labels for pod assignment | `{}` |
|
||||||
|
| `tolerations` | Node tolerations for pod assignment | `[]` |
|
||||||
|
| `affinity` | Node affinity for pod assignment | `{}` |
|
||||||
|
|
||||||
|
### Default Security Contexts
|
||||||
|
|
||||||
|
The default pod-level and container-level security contexts, below, adhere to the [restricted](https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted) Pod Security Standards policies.
|
||||||
|
|
||||||
|
Default pod-level securityContext:
|
||||||
|
```yaml
|
||||||
|
runAsNonRoot: true
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
```
|
||||||
|
|
||||||
|
Default containerSecurityContext:
|
||||||
|
```yaml
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
```
|
||||||
|
### Installing with a Values file
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ helm install answer -f values.yaml .
|
||||||
|
```
|
||||||
|
> **Tip**: You can use the default [values.yaml]
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
Publish the chart to Artifacthub and add proper installation instructions. E.G.
|
||||||
|
> **NOTE**: This is not currently a valid installation option.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ helm repo add answerdev https://charts.answer.dev/
|
||||||
|
$ helm repo update
|
||||||
|
$ helm install answerdev/answer -n mynamespace
|
||||||
|
```
|
|
@ -34,7 +34,7 @@ Create chart name and version as used by the chart label.
|
||||||
Common labels
|
Common labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "answer.labels" -}}
|
{{- define "answer.labels" -}}
|
||||||
helm.sh/chart: {{ .Release.Name }}
|
helm.sh/chart: {{ include "answer.chart" . }}
|
||||||
{{ include "answer.selectorLabels" . }}
|
{{ include "answer.selectorLabels" . }}
|
||||||
{{- if .Chart.AppVersion }}
|
{{- if .Chart.AppVersion }}
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
@ -46,6 +46,17 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
Selector labels
|
Selector labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "answer.selectorLabels" -}}
|
{{- define "answer.selectorLabels" -}}
|
||||||
app.kubernetes.io/name: answer
|
app.kubernetes.io/name: {{ include "answer.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "answer.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "answer.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: answer-config
|
|
||||||
namespace: {{ .Values.namespace | default "default" | quote }}
|
|
||||||
data:
|
|
||||||
default.yaml: |-
|
|
||||||
#
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "answer.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "answer.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- if not .Values.autoscaling.enabled }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "answer.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "answer.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "answer.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.port }}
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
{{- if .Values.env }}
|
||||||
|
env:
|
||||||
|
{{- range .Values.env }}
|
||||||
|
- name: {{ .name }}
|
||||||
|
{{- if .value | quote }}
|
||||||
|
value: {{ .value | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .valueFrom }}
|
||||||
|
valueFrom:
|
||||||
|
{{- toYaml .valueFrom | nindent 16 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: "/data"
|
||||||
|
{{- if .Values.extraContainers }}
|
||||||
|
{{- toYaml .Values.extraContainers | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "answer.fullname" . }}-claim
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end -}}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,28 @@
|
||||||
|
{{- if .Values.autoscaling.enabled }}
|
||||||
|
apiVersion: autoscaling/v2beta1
|
||||||
|
kind: HorizontalPodAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: {{ include "answer.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "answer.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
name: {{ include "answer.fullname" . }}
|
||||||
|
minReplicas: {{ .Values.autoscaling.minReplicas }}
|
||||||
|
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
|
||||||
|
metrics:
|
||||||
|
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: cpu
|
||||||
|
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
- type: Resource
|
||||||
|
resource:
|
||||||
|
name: memory
|
||||||
|
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,61 @@
|
||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
{{- $fullName := include "answer.fullname" . -}}
|
||||||
|
{{- $svcPort := .Values.service.port -}}
|
||||||
|
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
|
||||||
|
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
|
||||||
|
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
|
||||||
|
apiVersion: networking.k8s.io/v1beta1
|
||||||
|
{{- else -}}
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
{{- end }}
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ $fullName }}
|
||||||
|
labels:
|
||||||
|
{{- include "answer.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
{{- end }}
|
||||||
|
backend:
|
||||||
|
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
|
||||||
|
service:
|
||||||
|
name: {{ $fullName }}
|
||||||
|
port:
|
||||||
|
number: {{ $svcPort }}
|
||||||
|
{{- else }}
|
||||||
|
serviceName: {{ $fullName }}
|
||||||
|
servicePort: {{ $svcPort }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
|
@ -0,0 +1,25 @@
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: {{ include "answer.fullname" . }}-claim
|
||||||
|
{{- with .Values.persistence.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{ toYaml . | indent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "answer.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
{{- if (eq "-" .Values.persistence.storageClass) }}
|
||||||
|
storageClassName: ""
|
||||||
|
{{- else }}
|
||||||
|
storageClassName: "{{ .Values.persistence.storageClass }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.accessMode | quote }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size | quote }}
|
||||||
|
{{- end }}
|
|
@ -1,17 +1,15 @@
|
||||||
---
|
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "answer.fullname" . }}
|
name: {{ include "answer.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "answer.labels" . | nindent 4 }}
|
{{- include "answer.labels" . | nindent 4 }}
|
||||||
namespace: {{ .Values.namespace | default "default" | quote }}
|
|
||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: {{ .Values.service.type }}
|
||||||
ports:
|
ports:
|
||||||
- name: answer
|
- port: {{ .Values.service.port }}
|
||||||
port: 80
|
targetPort: http
|
||||||
targetPort: 80
|
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
name: http
|
||||||
selector:
|
selector:
|
||||||
{{- include "answer.selectorLabels" . | nindent 4 }}
|
{{- include "answer.selectorLabels" . | nindent 4 }}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{{- if .Values.serviceAccount.create -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ServiceAccount
|
||||||
|
metadata:
|
||||||
|
name: {{ include "answer.serviceAccountName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "answer.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
|
@ -1,31 +0,0 @@
|
||||||
---
|
|
||||||
apiVersion: apps/v1
|
|
||||||
kind: StatefulSet
|
|
||||||
metadata:
|
|
||||||
name: answer
|
|
||||||
namespace: {{ .Values.namespace | default "default" | quote }}
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "answer.labels" . | nindent 6 }}
|
|
||||||
serviceName: answer
|
|
||||||
replicas: 1
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
{{- include "answer.labels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: answer
|
|
||||||
image: nginx:stable
|
|
||||||
ports:
|
|
||||||
- containerPort: 80
|
|
||||||
name: answer-ui
|
|
||||||
volumeMounts:
|
|
||||||
- name: config
|
|
||||||
mountPath: "/etc/answer.yaml"
|
|
||||||
subPath: default.yaml
|
|
||||||
volumes:
|
|
||||||
- name: config
|
|
||||||
configMap:
|
|
||||||
name: answer-config
|
|
|
@ -1 +1,147 @@
|
||||||
namespace: default
|
# Default values for answer.
|
||||||
|
# This is a YAML-formatted file.
|
||||||
|
# Declare variables to be passed into your templates.
|
||||||
|
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: answerdev/answer
|
||||||
|
pullPolicy: Always
|
||||||
|
# Overrides the image tag whose default is the chart appVersion.
|
||||||
|
tag: "latest"
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
# Configure environment variables below
|
||||||
|
# https://answer.dev/docs/env
|
||||||
|
env:
|
||||||
|
- name: LOG_LEVEL
|
||||||
|
# [DEBUG INFO WARN ERROR]
|
||||||
|
value: "INFO"
|
||||||
|
# uncomment the below values to use AUTO_INSTALL and not have to go through the setup process.
|
||||||
|
# Once used to do the initial setup, these variables wont be used moving forward.
|
||||||
|
# You must at a minimum comment AUTO_INSTALL after initial setup to prevent an error about the database already being initiated.
|
||||||
|
# - name: AUTO_INSTALL
|
||||||
|
# value: "true"
|
||||||
|
# - name: DB_TYPE
|
||||||
|
# value: "sqlite3"
|
||||||
|
# # DB_FILE Only for sqlite3
|
||||||
|
# - name: DB_FILE
|
||||||
|
# value: "/data/answer.db"
|
||||||
|
# - name: LANGUAGE
|
||||||
|
# value: "en-US"
|
||||||
|
# - name: SITE_NAME
|
||||||
|
# value: "MyAnswer"
|
||||||
|
# - name: SITE_URL
|
||||||
|
# value: "http://localhost:80"
|
||||||
|
# - name: CONTACT_EMAIL
|
||||||
|
# value: "support@mydomain.com"
|
||||||
|
# - name: ADMIN_NAME
|
||||||
|
# # lowercase
|
||||||
|
# value: "myadmin"
|
||||||
|
# - name: ADMIN_PASSWORD
|
||||||
|
# # 32 Characters MAX
|
||||||
|
# value: "MyInsecurePasswordInTheRepo!"
|
||||||
|
# # Use valueFrom to use a secret
|
||||||
|
# # valueFrom:
|
||||||
|
# # secretKeyRef:
|
||||||
|
# # key: answer-admin-password
|
||||||
|
# # name: answer-secrets
|
||||||
|
# - name: ADMIN_EMAIL
|
||||||
|
# value: "myAdmin@mydomain.com"
|
||||||
|
|
||||||
|
# Configure extra containers
|
||||||
|
extraContainers: []
|
||||||
|
# - name: cloudsql-proxy
|
||||||
|
# image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.1.2
|
||||||
|
# command:
|
||||||
|
# - /cloud-sql-proxy
|
||||||
|
# args:
|
||||||
|
# - project:region:instance
|
||||||
|
# - --port=5432
|
||||||
|
# - --auto-iam-authn
|
||||||
|
# ports:
|
||||||
|
# - containerPort: 5432
|
||||||
|
|
||||||
|
# Persistence for the /data volume
|
||||||
|
# Without persistence, your uploads and config.yaml will not be remembered between restarts.
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
# If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||||
|
# If undefined (the default) or set to null, no storageClassName spec is
|
||||||
|
# set, choosing the default provisioner. (gp2 on AWS, standard on
|
||||||
|
# GKE, AWS & OpenStack)
|
||||||
|
# storageClass: "-"
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 5Gi
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
imagePullSecrets: []
|
||||||
|
nameOverride: ""
|
||||||
|
fullnameOverride: ""
|
||||||
|
|
||||||
|
serviceAccount:
|
||||||
|
# Specifies whether a service account should be created
|
||||||
|
create: true
|
||||||
|
# Annotations to add to the service account
|
||||||
|
annotations: {}
|
||||||
|
# The name of the service account to use.
|
||||||
|
# If not set and create is true, a name is generated using the fullname template
|
||||||
|
name: ""
|
||||||
|
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
|
podSecurityContext: {}
|
||||||
|
# fsGroup: 2000
|
||||||
|
|
||||||
|
securityContext: {}
|
||||||
|
# capabilities:
|
||||||
|
# drop:
|
||||||
|
# - ALL
|
||||||
|
# readOnlyRootFilesystem: true
|
||||||
|
# runAsNonRoot: true
|
||||||
|
# runAsUser: 1000
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: ""
|
||||||
|
annotations: {}
|
||||||
|
# kubernetes.io/ingress.class: nginx
|
||||||
|
# kubernetes.io/tls-acme: "true"
|
||||||
|
hosts:
|
||||||
|
- host: answer.local
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
tls: []
|
||||||
|
# - secretName: answer-tls
|
||||||
|
# hosts:
|
||||||
|
# - answer.local
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
# We usually recommend not to specify default resources and to leave this as a conscious
|
||||||
|
# choice for the user. This also increases chances charts run on environments with little
|
||||||
|
# resources, such as Minikube. If you do want to specify resources, uncomment the following
|
||||||
|
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
|
||||||
|
# limits:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
# requests:
|
||||||
|
# cpu: 100m
|
||||||
|
# memory: 128Mi
|
||||||
|
|
||||||
|
autoscaling:
|
||||||
|
enabled: false
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 100
|
||||||
|
targetCPUUtilizationPercentage: 80
|
||||||
|
# targetMemoryUtilizationPercentage: 80
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
affinity: {}
|
|
@ -53,6 +53,7 @@ func runApp() {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
constant.Version = Version
|
constant.Version = Version
|
||||||
|
constant.Revision = Revision
|
||||||
schema.AppStartTime = time.Now()
|
schema.AppStartTime = time.Now()
|
||||||
|
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
|
@ -165,8 +165,8 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
|
||||||
questionActivityRepo := activity.NewQuestionActivityRepo(dataData, activityRepo, userRankRepo)
|
questionActivityRepo := activity.NewQuestionActivityRepo(dataData, activityRepo, userRankRepo)
|
||||||
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, questionActivityRepo)
|
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, questionActivityRepo)
|
||||||
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService, dataData)
|
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, revisionService, metaService, collectionCommon, answerActivityService, dataData)
|
||||||
questionController := controller.NewQuestionController(questionService, rankService)
|
|
||||||
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService)
|
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService)
|
||||||
|
questionController := controller.NewQuestionController(questionService, answerService, rankService)
|
||||||
dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData)
|
dashboardService := dashboard.NewDashboardService(questionRepo, answerRepo, commentCommonRepo, voteRepo, userRepo, reportRepo, configRepo, siteInfoCommonService, serviceConf, dataData)
|
||||||
answerController := controller.NewAnswerController(answerService, rankService, dashboardService)
|
answerController := controller.NewAnswerController(answerService, rankService, dashboardService)
|
||||||
searchParser := search_parser.NewSearchParser(tagCommonService, userCommon)
|
searchParser := search_parser.NewSearchParser(tagCommonService, userCommon)
|
||||||
|
|
77
docs/docs.go
77
docs/docs.go
|
@ -3063,6 +3063,45 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/answer/api/v1/question/answer": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "add question and answer",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Question"
|
||||||
|
],
|
||||||
|
"summary": "add question and answer",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "question",
|
||||||
|
"name": "data",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/schema.QuestionAddByAnswer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/handler.RespBody"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/answer/api/v1/question/closemsglist": {
|
"/answer/api/v1/question/closemsglist": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@ -6751,6 +6790,41 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"schema.QuestionAddByAnswer": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"answer_content",
|
||||||
|
"content",
|
||||||
|
"tags",
|
||||||
|
"title"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"answer_content": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 65535,
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"description": "content",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 65535,
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"description": "tags",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/schema.TagItem"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "question title",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 150,
|
||||||
|
"minLength": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"schema.QuestionPageReq": {
|
"schema.QuestionPageReq": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -7230,6 +7304,9 @@ const docTemplate = `{
|
||||||
"login": {
|
"login": {
|
||||||
"$ref": "#/definitions/schema.SiteLoginResp"
|
"$ref": "#/definitions/schema.SiteLoginResp"
|
||||||
},
|
},
|
||||||
|
"revision": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"site_seo": {
|
"site_seo": {
|
||||||
"$ref": "#/definitions/schema.SiteSeoReq"
|
"$ref": "#/definitions/schema.SiteSeoReq"
|
||||||
},
|
},
|
||||||
|
|
|
@ -3051,6 +3051,45 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/answer/api/v1/question/answer": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "add question and answer",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Question"
|
||||||
|
],
|
||||||
|
"summary": "add question and answer",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "question",
|
||||||
|
"name": "data",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/schema.QuestionAddByAnswer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/handler.RespBody"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/answer/api/v1/question/closemsglist": {
|
"/answer/api/v1/question/closemsglist": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
@ -6739,6 +6778,41 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"schema.QuestionAddByAnswer": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"answer_content",
|
||||||
|
"content",
|
||||||
|
"tags",
|
||||||
|
"title"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"answer_content": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 65535,
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"description": "content",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 65535,
|
||||||
|
"minLength": 6
|
||||||
|
},
|
||||||
|
"tags": {
|
||||||
|
"description": "tags",
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/schema.TagItem"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"description": "question title",
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 150,
|
||||||
|
"minLength": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"schema.QuestionPageReq": {
|
"schema.QuestionPageReq": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -7218,6 +7292,9 @@
|
||||||
"login": {
|
"login": {
|
||||||
"$ref": "#/definitions/schema.SiteLoginResp"
|
"$ref": "#/definitions/schema.SiteLoginResp"
|
||||||
},
|
},
|
||||||
|
"revision": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"site_seo": {
|
"site_seo": {
|
||||||
"$ref": "#/definitions/schema.SiteSeoReq"
|
"$ref": "#/definitions/schema.SiteSeoReq"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1019,6 +1019,33 @@ definitions:
|
||||||
- tags
|
- tags
|
||||||
- title
|
- title
|
||||||
type: object
|
type: object
|
||||||
|
schema.QuestionAddByAnswer:
|
||||||
|
properties:
|
||||||
|
answer_content:
|
||||||
|
maxLength: 65535
|
||||||
|
minLength: 6
|
||||||
|
type: string
|
||||||
|
content:
|
||||||
|
description: content
|
||||||
|
maxLength: 65535
|
||||||
|
minLength: 6
|
||||||
|
type: string
|
||||||
|
tags:
|
||||||
|
description: tags
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/schema.TagItem'
|
||||||
|
type: array
|
||||||
|
title:
|
||||||
|
description: question title
|
||||||
|
maxLength: 150
|
||||||
|
minLength: 6
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- answer_content
|
||||||
|
- content
|
||||||
|
- tags
|
||||||
|
- title
|
||||||
|
type: object
|
||||||
schema.QuestionPageReq:
|
schema.QuestionPageReq:
|
||||||
properties:
|
properties:
|
||||||
orderCond:
|
orderCond:
|
||||||
|
@ -1354,6 +1381,8 @@ definitions:
|
||||||
$ref: '#/definitions/schema.SiteInterfaceResp'
|
$ref: '#/definitions/schema.SiteInterfaceResp'
|
||||||
login:
|
login:
|
||||||
$ref: '#/definitions/schema.SiteLoginResp'
|
$ref: '#/definitions/schema.SiteLoginResp'
|
||||||
|
revision:
|
||||||
|
type: string
|
||||||
site_seo:
|
site_seo:
|
||||||
$ref: '#/definitions/schema.SiteSeoReq'
|
$ref: '#/definitions/schema.SiteSeoReq'
|
||||||
theme:
|
theme:
|
||||||
|
@ -3794,6 +3823,30 @@ paths:
|
||||||
summary: update question
|
summary: update question
|
||||||
tags:
|
tags:
|
||||||
- Question
|
- Question
|
||||||
|
/answer/api/v1/question/answer:
|
||||||
|
post:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: add question and answer
|
||||||
|
parameters:
|
||||||
|
- description: question
|
||||||
|
in: body
|
||||||
|
name: data
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/schema.QuestionAddByAnswer'
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/handler.RespBody'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
summary: add question and answer
|
||||||
|
tags:
|
||||||
|
- Question
|
||||||
/answer/api/v1/question/closemsglist:
|
/answer/api/v1/question/closemsglist:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
|
13
go.mod
13
go.mod
|
@ -27,6 +27,7 @@ require (
|
||||||
github.com/mojocn/base64Captcha v1.3.5
|
github.com/mojocn/base64Captcha v1.3.5
|
||||||
github.com/ory/dockertest/v3 v3.9.1
|
github.com/ory/dockertest/v3 v3.9.1
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
|
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405
|
||||||
github.com/segmentfault/pacman v1.0.3
|
github.com/segmentfault/pacman v1.0.3
|
||||||
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0
|
github.com/segmentfault/pacman/contrib/cache/memory v0.0.0-20221219081300-f734f4a16aa0
|
||||||
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05
|
github.com/segmentfault/pacman/contrib/conf/viper v0.0.0-20221018072427-a15dd1434e05
|
||||||
|
@ -41,7 +42,7 @@ require (
|
||||||
github.com/tidwall/gjson v1.14.4
|
github.com/tidwall/gjson v1.14.4
|
||||||
github.com/yuin/goldmark v1.4.13
|
github.com/yuin/goldmark v1.4.13
|
||||||
golang.org/x/crypto v0.1.0
|
golang.org/x/crypto v0.1.0
|
||||||
golang.org/x/net v0.2.0
|
golang.org/x/net v0.7.0
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
modernc.org/sqlite v1.14.2
|
modernc.org/sqlite v1.14.2
|
||||||
|
@ -64,14 +65,20 @@ require (
|
||||||
github.com/docker/docker v20.10.7+incompatible // indirect
|
github.com/docker/docker v20.10.7+incompatible // indirect
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
|
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f // indirect
|
||||||
|
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 // indirect
|
||||||
|
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 // indirect
|
||||||
|
github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-errors/errors v1.0.1 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
github.com/go-openapi/jsonreference v0.20.0 // indirect
|
||||||
github.com/go-openapi/spec v0.20.7 // indirect
|
github.com/go-openapi/spec v0.20.7 // indirect
|
||||||
github.com/go-openapi/swag v0.22.3 // indirect
|
github.com/go-openapi/swag v0.22.3 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
|
github.com/golang/geo v0.0.0-20190812012225-f41920e961ce // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/gorilla/css v1.0.0 // indirect
|
github.com/gorilla/css v1.0.0 // indirect
|
||||||
|
@ -121,8 +128,8 @@ require (
|
||||||
go.uber.org/zap v1.23.0 // indirect
|
go.uber.org/zap v1.23.0 // indirect
|
||||||
golang.org/x/image v0.1.0 // indirect
|
golang.org/x/image v0.1.0 // indirect
|
||||||
golang.org/x/mod v0.6.0 // indirect
|
golang.org/x/mod v0.6.0 // indirect
|
||||||
golang.org/x/sys v0.2.0 // indirect
|
golang.org/x/sys v0.5.0 // indirect
|
||||||
golang.org/x/text v0.5.0 // indirect
|
golang.org/x/text v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.2.0 // indirect
|
golang.org/x/tools v0.2.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
|
|
26
go.sum
26
go.sum
|
@ -143,6 +143,14 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f h1:vqfYiZ+xF0xJvl9SZ1kovmMgKjaGZIz/Hn8JDQdyd9A=
|
||||||
|
github.com/dsoprea/go-exif v0.0.0-20190901173045-3ce78807c90f/go.mod h1:DmMpU91/Ax6BAwoRkjgRCr2rmgEgS4tsmatfV7M+U+c=
|
||||||
|
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48 h1:9zARagUAxQJjibcDy+0+koUMR6sbX38L49Bk2Vni628=
|
||||||
|
github.com/dsoprea/go-jpeg-image-structure v0.0.0-20190422055009-d6f9ba25cf48/go.mod h1:H1hAaFyv9cRV1ywoHvaqVoNSThBvWZ0JarRBcV+FSnE=
|
||||||
|
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696 h1:VGFnZAcLwPpt1sHlAxml+pGLZz9A2s+K/s1YNhPC91Y=
|
||||||
|
github.com/dsoprea/go-logging v0.0.0-20190624164917-c4f10aab7696/go.mod h1:Nm/x2ZUNRW6Fe5C3LxdY1PyZY5wmDv/s5dkPJ/VB3iA=
|
||||||
|
github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8 h1:SVQfy5rBFZXzvGkU2MZ0RzpS912/1sJrEJ+FMmeaC9U=
|
||||||
|
github.com/dsoprea/go-png-image-structure v0.0.0-20190624104353-c9b28dcdc5c8/go.mod h1:Bf0nmcDFFRQBjZwr9qY6c0zTxKQa+Q8YWZmlYxXGxY0=
|
||||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
|
@ -173,6 +181,8 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm
|
||||||
github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
|
||||||
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
|
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
|
||||||
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||||
|
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||||
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
@ -229,6 +239,8 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
|
github.com/golang/geo v0.0.0-20190812012225-f41920e961ce h1:rqIKPpIcEgiNn0KYNFYD34TbMO86l4woyhNzSP+Oegs=
|
||||||
|
github.com/golang/geo v0.0.0-20190812012225-f41920e961ce/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
@ -605,6 +617,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
|
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405 h1:2ieGkj4z/YPXVyQ2ayZUg3GwE1pYWd5f1RB6DzAOXKM=
|
||||||
|
github.com/scottleedavis/go-exif-remove v0.0.0-20230314195146-7e059d593405/go.mod h1:rIxVzVLKlBwLxO+lC+k/I4HJfRQcemg/f/76Xmmzsec=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||||
github.com/segmentfault/pacman v1.0.3 h1:/K8LJHQMiCaCIvC/e8GQITpYTEG6RH4KTLTZjPTghl4=
|
github.com/segmentfault/pacman v1.0.3 h1:/K8LJHQMiCaCIvC/e8GQITpYTEG6RH4KTLTZjPTghl4=
|
||||||
|
@ -851,8 +865,9 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -945,12 +960,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
@ -960,8 +977,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -1144,6 +1161,7 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gG
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
1248
i18n/de_DE.yaml
1248
i18n/de_DE.yaml
File diff suppressed because it is too large
Load Diff
|
@ -12,6 +12,17 @@ backend:
|
||||||
other: Unauthorized.
|
other: Unauthorized.
|
||||||
database_error:
|
database_error:
|
||||||
other: Data server error.
|
other: Data server error.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -100,6 +111,8 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Rank fail to meet the condition.
|
other: Rank fail to meet the condition.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Report handle failed.
|
other: Report handle failed.
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: No autorizado.
|
other: No autorizado.
|
||||||
database_error:
|
database_error:
|
||||||
other: Error en el servidor de datos.
|
other: Error en el servidor de datos.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Sin permiso para eliminar.
|
other: Sin permiso para eliminar.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Sin permiso para actualizar.
|
other: Sin permiso para actualizar.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Edición del comentario no permitida.
|
other: Edición del comentario no permitida.
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: El rango no cumple la condición.
|
other: El rango no cumple la condición.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Error en el manejador del reporte.
|
other: Error en el manejador del reporte.
|
||||||
not_found:
|
not_found:
|
||||||
other: Informe no encontrado.
|
other: Informe no encontrado.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Etiqueta no encontrada.
|
other: Etiqueta no encontrada.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -282,6 +299,7 @@ ui:
|
||||||
tag: Etiqueta
|
tag: Etiqueta
|
||||||
tags: Etiquetas
|
tags: Etiquetas
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Editar etiqueta
|
edit_tag: Editar etiqueta
|
||||||
ask_a_question: Añadir Pregunta
|
ask_a_question: Añadir Pregunta
|
||||||
edit_question: Editar Pregunta
|
edit_question: Editar Pregunta
|
||||||
|
@ -302,6 +320,9 @@ ui:
|
||||||
upgrade: Actualización de Answer
|
upgrade: Actualización de Answer
|
||||||
maintenance: Mantenimiento del sitio web
|
maintenance: Mantenimiento del sitio web
|
||||||
users: Usuarios
|
users: Usuarios
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notificaciones
|
title: Notificaciones
|
||||||
inbox: Buzón de entrada
|
inbox: Buzón de entrada
|
||||||
|
@ -454,6 +475,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancelar
|
btn_cancel: Cancelar
|
||||||
btn_submit: Enviar
|
btn_submit: Enviar
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Creado
|
created_at: Creado
|
||||||
edited_at: Editado
|
edited_at: Editado
|
||||||
|
@ -518,6 +540,7 @@ ui:
|
||||||
Utiliza los comentarios para pedir más información o sugerir mejoras y modificaciones. Evita responder preguntas en los comentarios.
|
Utiliza los comentarios para pedir más información o sugerir mejoras y modificaciones. Evita responder preguntas en los comentarios.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Usa comentarios para responder a otros usuarios o notificarles de cambios. Si estás añadiendo nueva información, edita tu publicación en vez de comentar.
|
Usa comentarios para responder a otros usuarios o notificarles de cambios. Si estás añadiendo nueva información, edita tu publicación en vez de comentar.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Editar respuesta
|
title: Editar respuesta
|
||||||
default_reason: Editar respuesta
|
default_reason: Editar respuesta
|
||||||
|
@ -767,6 +790,11 @@ ui:
|
||||||
answered: respondida
|
answered: respondida
|
||||||
closed_in: Cerrado el
|
closed_in: Cerrado el
|
||||||
show_exist: Mostrar una pregunta existente.
|
show_exist: Mostrar una pregunta existente.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Respuestas
|
title: Respuestas
|
||||||
score: Puntuación
|
score: Puntuación
|
||||||
|
@ -783,7 +811,14 @@ ui:
|
||||||
<p>¿Seguro que quieres añadir otra respuesta?</p><p>Puedes utilizar el enlace de edición para detallar y mejorar tu respuesta existente en su lugar.</p>
|
<p>¿Seguro que quieres añadir otra respuesta?</p><p>Puedes utilizar el enlace de edición para detallar y mejorar tu respuesta existente en su lugar.</p>
|
||||||
empty: La respuesta no puede estar vacía.
|
empty: La respuesta no puede estar vacía.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reabrir esta publicación
|
title: Reabrir esta publicación
|
||||||
content: '¿Seguro que quieres reabrir esta publicación?'
|
content: '¿Seguro que quieres reabrir esta publicación?'
|
||||||
success: Esta publicación ha sido reabierta
|
success: Esta publicación ha sido reabierta
|
||||||
|
@ -1002,13 +1037,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1223,6 +1256,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1388,8 +1424,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Usuarios
|
title: Usuarios
|
||||||
users_with_the_most_reputation: Usuarios con la reputación más alta
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Usuarios que más han votado
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Nuestor equipo de la comunidad
|
staffs: Nuestor equipo de la comunidad
|
||||||
reputation: reputación
|
reputation: reputación
|
||||||
votes: votos
|
votes: votos
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Non autorisé.
|
other: Non autorisé.
|
||||||
database_error:
|
database_error:
|
||||||
other: Erreur du serveur de données.
|
other: Erreur du serveur de données.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -35,9 +46,9 @@ backend:
|
||||||
error:
|
error:
|
||||||
admin:
|
admin:
|
||||||
cannot_update_their_password:
|
cannot_update_their_password:
|
||||||
other: You cannot modify your password.
|
other: Vous ne pouvez pas modifier votre mot de passe.
|
||||||
cannot_modify_self_status:
|
cannot_modify_self_status:
|
||||||
other: You cannot modify your status.
|
other: Vous ne pouvez pas modifier votre statut.
|
||||||
email_or_password_wrong:
|
email_or_password_wrong:
|
||||||
other: L'email et le mot de passe ne correspondent pas.
|
other: L'email et le mot de passe ne correspondent pas.
|
||||||
answer:
|
answer:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Pas de permission pour supprimer.
|
other: Pas de permission pour supprimer.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Pas de permission pour mettre à jour.
|
other: Pas de permission pour mettre à jour.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Les questions sont fermées et ne peuvent pas être ajoutées.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Les commentaires ne sont pas autorisés à être modifiés.
|
other: Les commentaires ne sont pas autorisés à être modifiés.
|
||||||
|
@ -85,7 +98,7 @@ backend:
|
||||||
other: Le nouveau mot de passe est le même que le précédent.
|
other: Le nouveau mot de passe est le même que le précédent.
|
||||||
question:
|
question:
|
||||||
already_deleted:
|
already_deleted:
|
||||||
other: This post has been deleted.
|
other: Ce message a été supprimé.
|
||||||
not_found:
|
not_found:
|
||||||
other: Question non trouvée.
|
other: Question non trouvée.
|
||||||
cannot_deleted:
|
cannot_deleted:
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Le rang ne remplit pas la condition.
|
other: Le rang ne remplit pas la condition.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: La gestion du rapport a échoué.
|
other: La gestion du rapport a échoué.
|
||||||
not_found:
|
not_found:
|
||||||
other: Rapport non trouvé.
|
other: Rapport non trouvé.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Le tag existe déjà.
|
||||||
not_found:
|
not_found:
|
||||||
other: Tag non trouvé.
|
other: Tag non trouvé.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Étiquette
|
tag: Étiquette
|
||||||
tags: Étiquettes
|
tags: Étiquettes
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Créer un tag
|
||||||
edit_tag: Modifier l'étiquette
|
edit_tag: Modifier l'étiquette
|
||||||
ask_a_question: Ajouter une question
|
ask_a_question: Ajouter une question
|
||||||
edit_question: Modifier la question
|
edit_question: Modifier la question
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Mise à jour d'Answer
|
upgrade: Mise à jour d'Answer
|
||||||
maintenance: Maintenance du site
|
maintenance: Maintenance du site
|
||||||
users: Utilisateurs
|
users: Utilisateurs
|
||||||
|
http_404: Erreur HTTP 404
|
||||||
|
http_50X: Erreur HTTP 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notifications
|
title: Notifications
|
||||||
inbox: Boîte de réception
|
inbox: Boîte de réception
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Le nom doit contenir moins de 35 caractères.
|
range: Le nom doit contenir moins de 35 caractères.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL simplifiée
|
label: URL simplifiée
|
||||||
desc: 'Doit utiliser le jeu de caractères "a-z", "0-9", "+ # - ."'
|
desc: Titre de 35 caractères maximum.
|
||||||
msg:
|
msg:
|
||||||
empty: L'URL ne peut pas être vide.
|
empty: L'URL ne peut pas être vide.
|
||||||
range: Titre de 35 caractères maximum.
|
range: Titre de 35 caractères maximum.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Annuler
|
btn_cancel: Annuler
|
||||||
btn_submit: Valider
|
btn_submit: Valider
|
||||||
|
btn_post: Publier un nouveau tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Créé
|
created_at: Créé
|
||||||
edited_at: Modifié
|
edited_at: Modifié
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Utilisez les commentaires pour demander plus d'informations ou suggérer des améliorations. Évitez de répondre aux questions dans les commentaires.
|
Utilisez les commentaires pour demander plus d'informations ou suggérer des améliorations. Évitez de répondre aux questions dans les commentaires.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Utilisez des commentaires pour répondre à d'autres utilisateurs ou leur signaler des modifications. Si vous ajoutez de nouvelles informations, modifiez votre message au lieu de commenter.
|
Utilisez des commentaires pour répondre à d'autres utilisateurs ou leur signaler des modifications. Si vous ajoutez de nouvelles informations, modifiez votre message au lieu de commenter.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Modifier la réponse
|
title: Modifier la réponse
|
||||||
default_reason: Modifier la réponse
|
default_reason: Modifier la réponse
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: répondu
|
answered: répondu
|
||||||
closed_in: Fermé dans
|
closed_in: Fermé dans
|
||||||
show_exist: Afficher la question existante.
|
show_exist: Afficher la question existante.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Réponses
|
title: Réponses
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Êtes-vous sûr de vouloir ajouter une autre réponse ?</p><p>Vous pouvez utiliser le lien d'édition pour affiner et améliorer votre réponse existante.</p>
|
<p>Êtes-vous sûr de vouloir ajouter une autre réponse ?</p><p>Vous pouvez utiliser le lien d'édition pour affiner et améliorer votre réponse existante.</p>
|
||||||
empty: La réponse ne peut être vide.
|
empty: La réponse ne peut être vide.
|
||||||
characters: le contenu doit comporter au moins 6 caractères.
|
characters: le contenu doit comporter au moins 6 caractères.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Rouvrir ce message
|
title: Rouvrir ce message
|
||||||
content: Êtes-vous sûr de vouloir rouvrir ?
|
content: Êtes-vous sûr de vouloir rouvrir ?
|
||||||
success: Ce message a été rouvert
|
success: Ce message a été rouvert
|
||||||
|
@ -788,7 +823,7 @@ ui:
|
||||||
approve: Approuver
|
approve: Approuver
|
||||||
reject: Rejeter
|
reject: Rejeter
|
||||||
skip: Ignorer
|
skip: Ignorer
|
||||||
discard_draft: Discard draft
|
discard_draft: Abandonner le brouillon
|
||||||
search:
|
search:
|
||||||
title: Résultats de la recherche
|
title: Résultats de la recherche
|
||||||
keywords: Mots-clés
|
keywords: Mots-clés
|
||||||
|
@ -977,14 +1012,12 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: réponses
|
answers: réponses
|
||||||
accepted: Accepté
|
accepted: Accepté
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Nous sommes désolés, mais cette page n’existe pas."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Retour à la page d'accueil
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
back_home: Back to homepage
|
||||||
desc: Le serveur a rencontré une erreur et n'a pas pu répondre à votre requête.
|
|
||||||
back_home: Retour à la page d'accueil
|
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "Nous sommes en maintenance, nous serons bientôt de retour."
|
desc: "Nous sommes en maintenance, nous serons bientôt de retour."
|
||||||
nav_menus:
|
nav_menus:
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Fuseau Horaire
|
label: Fuseau Horaire
|
||||||
msg: Le fuseau horaire ne peut pas être vide.
|
msg: Le fuseau horaire ne peut pas être vide.
|
||||||
text: Choisissez une ville dans le même fuseau horaire que vous.
|
text: Choisissez une ville dans le même fuseau horaire que vous.
|
||||||
|
avatar:
|
||||||
|
label: Avatar par défaut
|
||||||
|
text: Pour les utilisateurs sans avatar personnalisé.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "Nous n'avons rien pu trouver."
|
no_data: "Nous n'avons rien pu trouver."
|
||||||
users:
|
users:
|
||||||
title: Utilisateurs
|
title: Utilisateurs
|
||||||
users_with_the_most_reputation: Utilisateurs avec les scores de réputation les plus élevés
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Utilisateurs qui ont le plus voté
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Staff de la communauté
|
staffs: Staff de la communauté
|
||||||
reputation: réputation
|
reputation: réputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
@ -1372,7 +1408,7 @@ ui:
|
||||||
leave_page: Voulez-vous vraiment quitter la page ?
|
leave_page: Voulez-vous vraiment quitter la page ?
|
||||||
changes_not_save: Impossible d'enregistrer vos modifications.
|
changes_not_save: Impossible d'enregistrer vos modifications.
|
||||||
draft:
|
draft:
|
||||||
discard_confirm: Are you sure you want to discard your draft?
|
discard_confirm: Êtes-vous sûr de vouloir abandonner ce brouillon ?
|
||||||
messages:
|
messages:
|
||||||
post_deleted: This post has been deleted.
|
post_deleted: Ce message a été supprimé.
|
||||||
|
|
||||||
|
|
|
@ -39,3 +39,6 @@ language_options:
|
||||||
- label: "Tiếng Việt"
|
- label: "Tiếng Việt"
|
||||||
value: "vi_VN"
|
value: "vi_VN"
|
||||||
progress: 0
|
progress: 0
|
||||||
|
- label: "Slovak"
|
||||||
|
value: "sk_SK"
|
||||||
|
progress: 100
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Tidak diizinkan.
|
other: Tidak diizinkan.
|
||||||
database_error:
|
database_error:
|
||||||
other: Kesalahan data server.
|
other: Kesalahan data server.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Tidak memiliki izin untuk menghapus.
|
other: Tidak memiliki izin untuk menghapus.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Tidak memiliki izin untuk memperbaharui.
|
other: Tidak memiliki izin untuk memperbaharui.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Komentar tidak boleh diedit.
|
other: Komentar tidak boleh diedit.
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Peringkat gagal memenuhi syarat.
|
other: Peringkat gagal memenuhi syarat.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Laporan penanganan gagal.
|
other: Laporan penanganan gagal.
|
||||||
not_found:
|
not_found:
|
||||||
other: Laporan tidak ditemukan.
|
other: Laporan tidak ditemukan.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Tag tidak ditemukan.
|
other: Tag tidak ditemukan.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
tags: Tags
|
tags: Tags
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Ubah Tag
|
edit_tag: Ubah Tag
|
||||||
ask_a_question: Tambahkan Pertanyaan
|
ask_a_question: Tambahkan Pertanyaan
|
||||||
edit_question: Sunting Pertanyaan
|
edit_question: Sunting Pertanyaan
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Meng-upgrade Answer
|
upgrade: Meng-upgrade Answer
|
||||||
maintenance: Pemeliharaan Website
|
maintenance: Pemeliharaan Website
|
||||||
users: Pengguna
|
users: Pengguna
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Pemberitahuan
|
title: Pemberitahuan
|
||||||
inbox: Kotak Masuk
|
inbox: Kotak Masuk
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Display name up to 35 characters.
|
range: Display name up to 35 characters.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL Slug
|
label: URL Slug
|
||||||
desc: 'Must use the character set "a-z", "0-9", "+ # - ."'
|
desc: URL slug up to 35 characters.
|
||||||
msg:
|
msg:
|
||||||
empty: URL slug cannot be empty.
|
empty: URL slug cannot be empty.
|
||||||
range: URL slug up to 35 characters.
|
range: URL slug up to 35 characters.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancel
|
btn_cancel: Cancel
|
||||||
btn_submit: Submit
|
btn_submit: Submit
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Dibuat
|
created_at: Dibuat
|
||||||
edited_at: Disunting
|
edited_at: Disunting
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Gunakan komentar untuk meminta informasi lebih lanjut atau menyarankan perbaikan. Hindari menjawab pertanyaan di komentar.
|
Gunakan komentar untuk meminta informasi lebih lanjut atau menyarankan perbaikan. Hindari menjawab pertanyaan di komentar.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Gunakan komentar untuk membalas pengguna lain atau memberi tahu mereka tentang perubahan. Jika Anda menambahkan informasi baru, cukup edit posting Anda.
|
Gunakan komentar untuk membalas pengguna lain atau memberi tahu mereka tentang perubahan. Jika Anda menambahkan informasi baru, cukup edit posting Anda.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Sunting jawaban
|
title: Sunting jawaban
|
||||||
default_reason: Edit jawaban
|
default_reason: Edit jawaban
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: dijawab
|
answered: dijawab
|
||||||
closed_in: Ditutup pada
|
closed_in: Ditutup pada
|
||||||
show_exist: Gunakan pertanyaan yang sudah ada.
|
show_exist: Gunakan pertanyaan yang sudah ada.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Jawaban
|
title: Jawaban
|
||||||
score: Nilai
|
score: Nilai
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Yakin ingin menambahkan jawaban lain?</p><p>Sebagai gantinya, Anda dapat menggunakan tautan edit untuk menyaring dan menyempurnakan jawaban anda.</p>
|
<p>Yakin ingin menambahkan jawaban lain?</p><p>Sebagai gantinya, Anda dapat menggunakan tautan edit untuk menyaring dan menyempurnakan jawaban anda.</p>
|
||||||
empty: Jawaban tidak boleh kosong.
|
empty: Jawaban tidak boleh kosong.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Buka kembali postingan ini
|
title: Buka kembali postingan ini
|
||||||
content: Kamu yakin ingin membuka kembali?
|
content: Kamu yakin ingin membuka kembali?
|
||||||
success: Postingan ini telah dibuka kembali
|
success: Postingan ini telah dibuka kembali
|
||||||
|
@ -977,14 +1012,12 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Sayangnya, halaman ini tidak ada."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Kembali ke beranda
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
back_home: Back to homepage
|
||||||
desc: Server mengalami kesalahan internal dan tidak dapat menyelesaikan permintaan Anda.
|
|
||||||
back_home: Kembali ke beranda
|
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
nav_menus:
|
nav_menus:
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Non autorizzato
|
other: Non autorizzato
|
||||||
database_error:
|
database_error:
|
||||||
other: Errore server dati
|
other: Errore server dati
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Permesso per cancellare mancante.
|
other: Permesso per cancellare mancante.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Nessun permesso per l'aggiornamento.
|
other: Nessun permesso per l'aggiornamento.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Non si hanno di privilegi sufficienti per modificare il commento
|
other: Non si hanno di privilegi sufficienti per modificare il commento
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Condizioni non valide per il grado
|
other: Condizioni non valide per il grado
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Gestione del report fallita
|
other: Gestione del report fallita
|
||||||
not_found:
|
not_found:
|
||||||
other: Report non trovato
|
other: Report non trovato
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Etichetta non trovata
|
other: Etichetta non trovata
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
tags: Tags
|
tags: Tags
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Modifica Tag
|
edit_tag: Modifica Tag
|
||||||
ask_a_question: Aggiungi una domanda
|
ask_a_question: Aggiungi una domanda
|
||||||
edit_question: Modifica Domanda
|
edit_question: Modifica Domanda
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Answer Upgrade
|
upgrade: Answer Upgrade
|
||||||
maintenance: Website Maintenance
|
maintenance: Website Maintenance
|
||||||
users: Users
|
users: Users
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notifications
|
title: Notifications
|
||||||
inbox: Inbox
|
inbox: Inbox
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancel
|
btn_cancel: Cancel
|
||||||
btn_submit: Submit
|
btn_submit: Submit
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Created
|
created_at: Created
|
||||||
edited_at: Edited
|
edited_at: Edited
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
222
i18n/ja_JP.yaml
222
i18n/ja_JP.yaml
|
@ -2,23 +2,34 @@
|
||||||
backend:
|
backend:
|
||||||
base:
|
base:
|
||||||
success:
|
success:
|
||||||
other: Success.
|
other: 成功
|
||||||
unknown:
|
unknown:
|
||||||
other: Unknown error.
|
other: 不明なエラー
|
||||||
request_format_error:
|
request_format_error:
|
||||||
other: Request format is not valid.
|
other: リクエスト形式が無効です。
|
||||||
unauthorized_error:
|
unauthorized_error:
|
||||||
other: Unauthorized.
|
other: 権限がありません。
|
||||||
database_error:
|
database_error:
|
||||||
other: Data server error.
|
other: データサーバーエラー
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
other: User
|
other: ユーザー
|
||||||
admin:
|
admin:
|
||||||
other: Admin
|
other: 管理者
|
||||||
moderator:
|
moderator:
|
||||||
other: Moderator
|
other: モデレーター
|
||||||
description:
|
description:
|
||||||
user:
|
user:
|
||||||
other: Default with no special access.
|
other: Default with no special access.
|
||||||
|
@ -27,90 +38,96 @@ backend:
|
||||||
moderator:
|
moderator:
|
||||||
other: Has access to all posts except admin settings.
|
other: Has access to all posts except admin settings.
|
||||||
email:
|
email:
|
||||||
other: Email
|
other: メールアドレス
|
||||||
password:
|
password:
|
||||||
other: Password
|
other: パスワード
|
||||||
email_or_password_wrong_error:
|
email_or_password_wrong_error:
|
||||||
other: Email and password do not match.
|
other: メールアドレスとパスワードが一致しません。
|
||||||
error:
|
error:
|
||||||
admin:
|
admin:
|
||||||
cannot_update_their_password:
|
cannot_update_their_password:
|
||||||
other: You cannot modify your password.
|
other: パスワードは変更できません。
|
||||||
cannot_modify_self_status:
|
cannot_modify_self_status:
|
||||||
other: You cannot modify your status.
|
other: ステータスを変更できません。
|
||||||
email_or_password_wrong:
|
email_or_password_wrong:
|
||||||
other: Email and password do not match.
|
other: メールアドレスとパスワードが一致しません。
|
||||||
answer:
|
answer:
|
||||||
not_found:
|
not_found:
|
||||||
other: Answer do not found.
|
other: Answer do not found.
|
||||||
cannot_deleted:
|
cannot_deleted:
|
||||||
other: No permission to delete.
|
other: 削除する権限がありません。
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: No permission to update.
|
other: 更新する権限がありません。
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: 質問はクローズされて、追加できません。
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Comment are not allowed to edit.
|
other: コメントを編集することはできません。
|
||||||
not_found:
|
not_found:
|
||||||
other: Comment not found.
|
other: コメントが見つかりません。
|
||||||
cannot_edit_after_deadline:
|
cannot_edit_after_deadline:
|
||||||
other: The comment time has been too long to modify.
|
other: コメント時間が長すぎて変更できません。
|
||||||
email:
|
email:
|
||||||
duplicate:
|
duplicate:
|
||||||
other: Email already exists.
|
other: メールアドレスは既に存在しています。
|
||||||
need_to_be_verified:
|
need_to_be_verified:
|
||||||
other: Email should be verified.
|
other: 電子メールを確認する必要があります。
|
||||||
verify_url_expired:
|
verify_url_expired:
|
||||||
other: Email verified URL has expired, please resend the email.
|
other: メール認証済みURLの有効期限が切れています。メールを再送信してください。
|
||||||
lang:
|
lang:
|
||||||
not_found:
|
not_found:
|
||||||
other: Language file not found.
|
other: 言語ファイルが見つかりません。
|
||||||
object:
|
object:
|
||||||
captcha_verification_failed:
|
captcha_verification_failed:
|
||||||
other: Captcha wrong.
|
other: Captchaが間違っています。
|
||||||
disallow_follow:
|
disallow_follow:
|
||||||
other: You are not allowed to follow.
|
other: フォローが許可されていません。
|
||||||
disallow_vote:
|
disallow_vote:
|
||||||
other: You are not allowed to vote.
|
other: 投票が許可されていません。
|
||||||
disallow_vote_your_self:
|
disallow_vote_your_self:
|
||||||
other: You can't vote for your own post.
|
other: 自分の投稿には投票できません。
|
||||||
not_found:
|
not_found:
|
||||||
other: Object not found.
|
other: オブジェクトが見つかりません。
|
||||||
verification_failed:
|
verification_failed:
|
||||||
other: Verification failed.
|
other: 認証に失敗しました。
|
||||||
email_or_password_incorrect:
|
email_or_password_incorrect:
|
||||||
other: Email and password do not match.
|
other: メールアドレスとパスワードが一致しません。
|
||||||
old_password_verification_failed:
|
old_password_verification_failed:
|
||||||
other: The old password verification failed
|
other: 古いパスワードの確認に失敗しました。
|
||||||
new_password_same_as_previous_setting:
|
new_password_same_as_previous_setting:
|
||||||
other: The new password is the same as the previous one.
|
other: 新しいパスワードは前のパスワードと同じです。
|
||||||
question:
|
question:
|
||||||
already_deleted:
|
already_deleted:
|
||||||
other: This post has been deleted.
|
other: この投稿は削除されました。
|
||||||
not_found:
|
not_found:
|
||||||
other: Question not found.
|
other: 質問が見つかりません。
|
||||||
cannot_deleted:
|
cannot_deleted:
|
||||||
other: No permission to delete.
|
other: 削除する権限がありません。
|
||||||
cannot_close:
|
cannot_close:
|
||||||
other: No permission to close.
|
other: クローズする権限がありません。
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: No permission to update.
|
other: 更新する権限がありません。
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Rank fail to meet the condition.
|
other: ランクは条件を満たしていません。
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Report handle failed.
|
other: レポートの処理に失敗しました。
|
||||||
not_found:
|
not_found:
|
||||||
other: Report not found.
|
other: レポートが見つかりません。
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: タグは既に存在します。
|
||||||
not_found:
|
not_found:
|
||||||
other: Tag not found.
|
other: タグが見つかりません。
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
other: Recommend Tag is not exist.
|
other: 推奨タグは存在しません。
|
||||||
recommend_tag_enter:
|
recommend_tag_enter:
|
||||||
other: Please enter at least one required tag.
|
other: 少なくとも 1 つの必須タグを入力してください。
|
||||||
not_contain_synonym_tags:
|
not_contain_synonym_tags:
|
||||||
other: Should not contain synonym tags.
|
other: 同義語のタグを含めないでください。
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: No permission to update.
|
other: No permission to update.
|
||||||
is_used_cannot_delete:
|
is_used_cannot_delete:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
tags: Tags
|
tags: Tags
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Edit Tag
|
edit_tag: Edit Tag
|
||||||
ask_a_question: Add Question
|
ask_a_question: Add Question
|
||||||
edit_question: Edit Question
|
edit_question: Edit Question
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Answer Upgrade
|
upgrade: Answer Upgrade
|
||||||
maintenance: Website Maintenance
|
maintenance: Website Maintenance
|
||||||
users: Users
|
users: Users
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notifications
|
title: Notifications
|
||||||
inbox: Inbox
|
inbox: Inbox
|
||||||
|
@ -294,12 +315,12 @@ ui:
|
||||||
end: You don't meet a community guideline.
|
end: You don't meet a community guideline.
|
||||||
editor:
|
editor:
|
||||||
blockquote:
|
blockquote:
|
||||||
text: Blockquote
|
text: 引用
|
||||||
bold:
|
bold:
|
||||||
text: Strong
|
text: Strong
|
||||||
chart:
|
chart:
|
||||||
text: Chart
|
text: Chart
|
||||||
flow_chart: Flow chart
|
flow_chart: フローチャート
|
||||||
sequence_diagram: Sequence diagram
|
sequence_diagram: Sequence diagram
|
||||||
class_diagram: Class diagram
|
class_diagram: Class diagram
|
||||||
state_diagram: State diagram
|
state_diagram: State diagram
|
||||||
|
@ -313,61 +334,61 @@ ui:
|
||||||
form:
|
form:
|
||||||
fields:
|
fields:
|
||||||
code:
|
code:
|
||||||
label: Code
|
label: コード
|
||||||
msg:
|
msg:
|
||||||
empty: Code cannot be empty.
|
empty: Code cannot be empty.
|
||||||
language:
|
language:
|
||||||
label: Language
|
label: 言語
|
||||||
placeholder: Automatic detection
|
placeholder: 自動検出
|
||||||
btn_cancel: Cancel
|
btn_cancel: キャンセル
|
||||||
btn_confirm: Add
|
btn_confirm: 追加
|
||||||
formula:
|
formula:
|
||||||
text: Formula
|
text: 数式
|
||||||
options:
|
options:
|
||||||
inline: Inline formula
|
inline: Inline formula
|
||||||
block: Block formula
|
block: Block formula
|
||||||
heading:
|
heading:
|
||||||
text: Heading
|
text: 見出し
|
||||||
options:
|
options:
|
||||||
h1: Heading 1
|
h1: 見出し1
|
||||||
h2: Heading 2
|
h2: 見出し2
|
||||||
h3: Heading 3
|
h3: 見出し3
|
||||||
h4: Heading 4
|
h4: 見出し4
|
||||||
h5: Heading 5
|
h5: 見出し5
|
||||||
h6: Heading 6
|
h6: 見出し6
|
||||||
help:
|
help:
|
||||||
text: Help
|
text: ヘルプ
|
||||||
hr:
|
hr:
|
||||||
text: Horizontal Rule
|
text: Horizontal Rule
|
||||||
image:
|
image:
|
||||||
text: Image
|
text: 画像
|
||||||
add_image: Add image
|
add_image: 画像を追加する
|
||||||
tab_image: Upload image
|
tab_image: 画像をアップロードする
|
||||||
form_image:
|
form_image:
|
||||||
fields:
|
fields:
|
||||||
file:
|
file:
|
||||||
label: Image File
|
label: 画像ファイル
|
||||||
btn: Select image
|
btn: 画像を選択する
|
||||||
msg:
|
msg:
|
||||||
empty: File cannot be empty.
|
empty: ファイルは空にできません。
|
||||||
only_image: Only image files are allowed.
|
only_image: 画像ファイルのみが許可されています。
|
||||||
max_size: File size cannot exceed 4MB.
|
max_size: ファイルサイズは4MBを超えることはできません。
|
||||||
desc:
|
desc:
|
||||||
label: Description
|
label: 説明
|
||||||
tab_url: Image URL
|
tab_url: 画像URL
|
||||||
form_url:
|
form_url:
|
||||||
fields:
|
fields:
|
||||||
url:
|
url:
|
||||||
label: Image URL
|
label: 画像URL
|
||||||
msg:
|
msg:
|
||||||
empty: Image URL cannot be empty.
|
empty: 画像のURLは空にできません。
|
||||||
name:
|
name:
|
||||||
label: Description
|
label: 説明
|
||||||
btn_cancel: Cancel
|
btn_cancel: キャンセル
|
||||||
btn_confirm: Add
|
btn_confirm: 追加
|
||||||
uploading: Uploading
|
uploading: アップロード中
|
||||||
indent:
|
indent:
|
||||||
text: Indent
|
text: インデント
|
||||||
outdent:
|
outdent:
|
||||||
text: Outdent
|
text: Outdent
|
||||||
italic:
|
italic:
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Display name up to 35 characters.
|
range: Display name up to 35 characters.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL Slug
|
label: URL Slug
|
||||||
desc: 'Must use the character set "a-z", "0-9", "+ # - ."'
|
desc: '文字セット「a-z」、「0-9」、「+ # -」を使用する必要があります。'
|
||||||
msg:
|
msg:
|
||||||
empty: URL slug cannot be empty.
|
empty: URL slug cannot be empty.
|
||||||
range: URL slug up to 35 characters.
|
range: URL slug up to 35 characters.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancel
|
btn_cancel: Cancel
|
||||||
btn_submit: Submit
|
btn_submit: Submit
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Created
|
created_at: Created
|
||||||
edited_at: Edited
|
edited_at: Edited
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -701,17 +724,17 @@ ui:
|
||||||
label: Email Notifications
|
label: Email Notifications
|
||||||
radio: "Answers to your questions, comments, and more"
|
radio: "Answers to your questions, comments, and more"
|
||||||
account:
|
account:
|
||||||
heading: Account
|
heading: アカウント
|
||||||
change_email_btn: Change email
|
change_email_btn: メールアドレスを変更する
|
||||||
change_pass_btn: Change password
|
change_pass_btn: パスワードを変更する
|
||||||
change_email_info: >-
|
change_email_info: >-
|
||||||
We've sent an email to that address. Please follow the confirmation instructions.
|
We've sent an email to that address. Please follow the confirmation instructions.
|
||||||
email:
|
email:
|
||||||
label: Email
|
label: メールアドレス
|
||||||
msg: Email cannot be empty.
|
msg: Email cannot be empty.
|
||||||
password_title: Password
|
password_title: パスワード
|
||||||
current_pass:
|
current_pass:
|
||||||
label: Current Password
|
label: 現在のパスワード
|
||||||
msg:
|
msg:
|
||||||
empty: Current Password cannot be empty.
|
empty: Current Password cannot be empty.
|
||||||
length: The length needs to be between 8 and 32.
|
length: The length needs to be between 8 and 32.
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Unauthorized.
|
other: Unauthorized.
|
||||||
database_error:
|
database_error:
|
||||||
other: Data server error.
|
other: Data server error.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: No permission to delete.
|
other: No permission to delete.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: No permission to update.
|
other: No permission to update.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Comment are not allowed to edit.
|
other: Comment are not allowed to edit.
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Rank fail to meet the condition.
|
other: Rank fail to meet the condition.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Report handle failed.
|
other: Report handle failed.
|
||||||
not_found:
|
not_found:
|
||||||
other: Report not found.
|
other: Report not found.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Tag not found.
|
other: Tag not found.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
tags: Tags
|
tags: Tags
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Edit Tag
|
edit_tag: Edit Tag
|
||||||
ask_a_question: Add Question
|
ask_a_question: Add Question
|
||||||
edit_question: Edit Question
|
edit_question: Edit Question
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Answer Upgrade
|
upgrade: Answer Upgrade
|
||||||
maintenance: Website Maintenance
|
maintenance: Website Maintenance
|
||||||
users: Users
|
users: Users
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notifications
|
title: Notifications
|
||||||
inbox: Inbox
|
inbox: Inbox
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancel
|
btn_cancel: Cancel
|
||||||
btn_submit: Submit
|
btn_submit: Submit
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Created
|
created_at: Created
|
||||||
edited_at: Edited
|
edited_at: Edited
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Não autorizado.
|
other: Não autorizado.
|
||||||
database_error:
|
database_error:
|
||||||
other: Erro no servidor de dados.
|
other: Erro no servidor de dados.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Sem permissão para remover.
|
other: Sem permissão para remover.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Sem permissão para atualizar.
|
other: Sem permissão para atualizar.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Não é possível alterar comentários.
|
other: Não é possível alterar comentários.
|
||||||
|
@ -68,7 +81,7 @@ backend:
|
||||||
captcha_verification_failed:
|
captcha_verification_failed:
|
||||||
other: O Captcha está incorreto.
|
other: O Captcha está incorreto.
|
||||||
disallow_follow:
|
disallow_follow:
|
||||||
other: Você não possui autorização suficiente para seguir.
|
other: Você não tem permissão para seguir.
|
||||||
disallow_vote:
|
disallow_vote:
|
||||||
other: Você não possui permissão para votar.
|
other: Você não possui permissão para votar.
|
||||||
disallow_vote_your_self:
|
disallow_vote_your_self:
|
||||||
|
@ -97,14 +110,18 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: O nível não consegue satisfazer a condição.
|
other: O nível não consegue satisfazer a condição.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Falha ao manusear relatório.
|
other: Falha ao manusear relatório.
|
||||||
not_found:
|
not_found:
|
||||||
other: Relatório não encontrado.
|
other: Relatório não encontrado.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Marcador não encontrado.
|
other: Marca não encontrada.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
other: O marcador recomendado não existe.
|
other: O marcador recomendado não existe.
|
||||||
recommend_tag_enter:
|
recommend_tag_enter:
|
||||||
|
@ -125,9 +142,9 @@ backend:
|
||||||
other: Tema não encontrado.
|
other: Tema não encontrado.
|
||||||
revision:
|
revision:
|
||||||
review_underway:
|
review_underway:
|
||||||
other: Não é possível neste momento, há uma versão na fila de análise.
|
other: Não é possível editar atualmente, há uma versão na fila de análise.
|
||||||
no_permission:
|
no_permission:
|
||||||
other: Sem permissão para realizar Revisão.
|
other: Sem permissão de modificação.
|
||||||
user:
|
user:
|
||||||
email_or_password_wrong:
|
email_or_password_wrong:
|
||||||
other:
|
other:
|
||||||
|
@ -135,7 +152,7 @@ backend:
|
||||||
not_found:
|
not_found:
|
||||||
other: Usuário não encontrado.
|
other: Usuário não encontrado.
|
||||||
suspended:
|
suspended:
|
||||||
other: O usuário foi suspenso.
|
other: O utilizador foi suspenso.
|
||||||
username_invalid:
|
username_invalid:
|
||||||
other: Nome de usuário inválido.
|
other: Nome de usuário inválido.
|
||||||
username_duplicate:
|
username_duplicate:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
tags: Tags
|
tags: Tags
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Edit Tag
|
edit_tag: Edit Tag
|
||||||
ask_a_question: Add Question
|
ask_a_question: Add Question
|
||||||
edit_question: Edit Question
|
edit_question: Edit Question
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Atualização do Answer
|
upgrade: Atualização do Answer
|
||||||
maintenance: Manutenção do website
|
maintenance: Manutenção do website
|
||||||
users: Usuários
|
users: Usuários
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notificações
|
title: Notificações
|
||||||
inbox: Caixa de entrada
|
inbox: Caixa de entrada
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Display name up to 35 characters.
|
range: Display name up to 35 characters.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL Slug
|
label: URL Slug
|
||||||
desc: 'Must use the character set "a-z", "0-9", "+ # - ."'
|
desc: URL slug up to 35 characters.
|
||||||
msg:
|
msg:
|
||||||
empty: URL slug cannot be empty.
|
empty: URL slug cannot be empty.
|
||||||
range: URL slug up to 35 characters.
|
range: URL slug up to 35 characters.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancel
|
btn_cancel: Cancel
|
||||||
btn_submit: Submit
|
btn_submit: Submit
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Created
|
created_at: Created
|
||||||
edited_at: Edited
|
edited_at: Edited
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Авторизация не выполнена.
|
other: Авторизация не выполнена.
|
||||||
database_error:
|
database_error:
|
||||||
other: Ошибка сервера данных.
|
other: Ошибка сервера данных.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Недостаточно прав для удаления.
|
other: Недостаточно прав для удаления.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Нет прав для обновления.
|
other: Нет прав для обновления.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Комментарий не может редактироваться.
|
other: Комментарий не может редактироваться.
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Ранг не соответствует условию.
|
other: Ранг не соответствует условию.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Не удалось обработать отчет.
|
other: Не удалось обработать отчет.
|
||||||
not_found:
|
not_found:
|
||||||
other: Отчет не найден.
|
other: Отчет не найден.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Тег не найден.
|
other: Тег не найден.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Тэг
|
tag: Тэг
|
||||||
tags: Теги
|
tags: Теги
|
||||||
tag_wiki: wiki тэг
|
tag_wiki: wiki тэг
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Изменить тег
|
edit_tag: Изменить тег
|
||||||
ask_a_question: Добавить вопрос
|
ask_a_question: Добавить вопрос
|
||||||
edit_question: Редактировать вопрос
|
edit_question: Редактировать вопрос
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Обновить ответ
|
upgrade: Обновить ответ
|
||||||
maintenance: Обслуживание сайта
|
maintenance: Обслуживание сайта
|
||||||
users: Пользователи
|
users: Пользователи
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Уведомления
|
title: Уведомления
|
||||||
inbox: Входящие
|
inbox: Входящие
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Отображаемое имя до 35 символов.
|
range: Отображаемое имя до 35 символов.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: Идентификатор URL
|
label: Идентификатор URL
|
||||||
desc: 'Необходимо использовать набор символов "a-z", "0-9", "+ # - ."'
|
desc: URL slug up to 35 characters.
|
||||||
msg:
|
msg:
|
||||||
empty: URL slug не может быть пустым.
|
empty: URL slug не может быть пустым.
|
||||||
range: URL slug до 35 символов.
|
range: URL slug до 35 символов.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Отмена
|
btn_cancel: Отмена
|
||||||
btn_submit: Отправить
|
btn_submit: Отправить
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Создано
|
created_at: Создано
|
||||||
edited_at: Отредактировано
|
edited_at: Отредактировано
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: İzin yok.
|
other: İzin yok.
|
||||||
database_error:
|
database_error:
|
||||||
other: Veri sunucu hatası.
|
other: Veri sunucu hatası.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: Silme izni yok.
|
other: Silme izni yok.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: Düzenleme izni yok.
|
other: Düzenleme izni yok.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Yorum düzenleme izni yok.
|
other: Yorum düzenleme izni yok.
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Rank fail to meet the condition.
|
other: Rank fail to meet the condition.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Rapor işlenemedi.
|
other: Rapor işlenemedi.
|
||||||
not_found:
|
not_found:
|
||||||
other: Rapor bulunamadı.
|
other: Rapor bulunamadı.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Etiket bulunamadı.
|
other: Etiket bulunamadı.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Etiket
|
tag: Etiket
|
||||||
tags: Etiketler
|
tags: Etiketler
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Etiketi Düzenle
|
edit_tag: Etiketi Düzenle
|
||||||
ask_a_question: Soru Ekle
|
ask_a_question: Soru Ekle
|
||||||
edit_question: Soruyu Düzenle
|
edit_question: Soruyu Düzenle
|
||||||
|
@ -280,7 +298,10 @@ ui:
|
||||||
install: Answer Installation
|
install: Answer Installation
|
||||||
upgrade: Answer Upgrade
|
upgrade: Answer Upgrade
|
||||||
maintenance: Website Bakımı
|
maintenance: Website Bakımı
|
||||||
users: Kullanıcı
|
users: Kullanıcılar
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Bildirimler
|
title: Bildirimler
|
||||||
inbox: Gelen Kutusu
|
inbox: Gelen Kutusu
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Display name up to 35 characters.
|
range: Display name up to 35 characters.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL Slug
|
label: URL Slug
|
||||||
desc: 'Must use the character set "a-z", "0-9", "+ # - ."'
|
desc: URL slug up to 35 characters.
|
||||||
msg:
|
msg:
|
||||||
empty: URL slug cannot be empty.
|
empty: URL slug cannot be empty.
|
||||||
range: URL slug up to 35 characters.
|
range: URL slug up to 35 characters.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: İptal Et
|
btn_cancel: İptal Et
|
||||||
btn_submit: Gönder
|
btn_submit: Gönder
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Oluşturuldu
|
created_at: Oluşturuldu
|
||||||
edited_at: Düzenlendi
|
edited_at: Düzenlendi
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: Unauthorized.
|
other: Unauthorized.
|
||||||
database_error:
|
database_error:
|
||||||
other: Data server error.
|
other: Data server error.
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: No permission to delete.
|
other: No permission to delete.
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: No permission to update.
|
other: No permission to update.
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: Comment are not allowed to edit.
|
other: Comment are not allowed to edit.
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: Rank fail to meet the condition.
|
other: Rank fail to meet the condition.
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: Report handle failed.
|
other: Report handle failed.
|
||||||
not_found:
|
not_found:
|
||||||
other: Report not found.
|
other: Report not found.
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: Tag not found.
|
other: Tag not found.
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: Tag
|
tag: Tag
|
||||||
tags: Tags
|
tags: Tags
|
||||||
tag_wiki: tag wiki
|
tag_wiki: tag wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: Edit Tag
|
edit_tag: Edit Tag
|
||||||
ask_a_question: Add Question
|
ask_a_question: Add Question
|
||||||
edit_question: Edit Question
|
edit_question: Edit Question
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Answer Upgrade
|
upgrade: Answer Upgrade
|
||||||
maintenance: Website Maintenance
|
maintenance: Website Maintenance
|
||||||
users: Users
|
users: Users
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: Notifications
|
title: Notifications
|
||||||
inbox: Inbox
|
inbox: Inbox
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: Display name up to 35 characters.
|
range: Display name up to 35 characters.
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL Slug
|
label: URL Slug
|
||||||
desc: 'Must use the character set "a-z", "0-9", "+ # - ."'
|
desc: URL slug up to 35 characters.
|
||||||
msg:
|
msg:
|
||||||
empty: URL slug cannot be empty.
|
empty: URL slug cannot be empty.
|
||||||
range: URL slug up to 35 characters.
|
range: URL slug up to 35 characters.
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: Description
|
label: Description
|
||||||
btn_cancel: Cancel
|
btn_cancel: Cancel
|
||||||
btn_submit: Submit
|
btn_submit: Submit
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: Created
|
created_at: Created
|
||||||
edited_at: Edited
|
edited_at: Edited
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
Use comments to ask for more information or suggest improvements. Avoid answering questions in comments.
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
Use comments to reply to other users or notify them of changes. If you are adding new information, edit your post instead of commenting.
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: Edit Answer
|
title: Edit Answer
|
||||||
default_reason: Edit answer
|
default_reason: Edit answer
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: answered
|
answered: answered
|
||||||
closed_in: Closed in
|
closed_in: Closed in
|
||||||
show_exist: Show existing question.
|
show_exist: Show existing question.
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: Answers
|
title: Answers
|
||||||
score: Score
|
score: Score
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
<p>Are you sure you want to add another answer?</p><p>You could use the edit link to refine and improve your existing answer, instead.</p>
|
||||||
empty: Answer cannot be empty.
|
empty: Answer cannot be empty.
|
||||||
characters: content must be at least 6 characters in length.
|
characters: content must be at least 6 characters in length.
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: Reopen this post
|
title: Reopen this post
|
||||||
content: Are you sure you want to reopen?
|
content: Are you sure you want to reopen?
|
||||||
success: This post has been reopened
|
success: This post has been reopened
|
||||||
|
@ -977,13 +1012,11 @@ ui:
|
||||||
votes: votes
|
votes: votes
|
||||||
answers: answers
|
answers: answers
|
||||||
accepted: Accepted
|
accepted: Accepted
|
||||||
page_404:
|
page_error:
|
||||||
http_error: HTTP Error 404
|
http_error: HTTP Error {{ code }}
|
||||||
desc: "Unfortunately, this page doesn't exist."
|
desc_403: You don’t have permission to access this page.
|
||||||
back_home: Back to homepage
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
page_50X:
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
http_error: HTTP Error 500
|
|
||||||
desc: The server encountered an error and could not complete your request.
|
|
||||||
back_home: Back to homepage
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "We are under maintenance, we'll be back soon."
|
desc: "We are under maintenance, we'll be back soon."
|
||||||
|
@ -1198,6 +1231,9 @@ ui:
|
||||||
label: Timezone
|
label: Timezone
|
||||||
msg: Timezone cannot be empty.
|
msg: Timezone cannot be empty.
|
||||||
text: Choose a city in the same timezone as you.
|
text: Choose a city in the same timezone as you.
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1363,8 +1399,8 @@ ui:
|
||||||
no_data: "We couldn't find anything."
|
no_data: "We couldn't find anything."
|
||||||
users:
|
users:
|
||||||
title: Users
|
title: Users
|
||||||
users_with_the_most_reputation: Users with the highest reputation scores
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: Users who voted the most
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: Our community staff
|
staffs: Our community staff
|
||||||
reputation: reputation
|
reputation: reputation
|
||||||
votes: votes
|
votes: votes
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: 未授权。
|
other: 未授权。
|
||||||
database_error:
|
database_error:
|
||||||
other: 数据服务器错误。
|
other: 数据服务器错误。
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: 举报
|
||||||
|
edit:
|
||||||
|
other: 编辑
|
||||||
|
delete:
|
||||||
|
other: 删除
|
||||||
|
close:
|
||||||
|
other: 关闭
|
||||||
|
reopen:
|
||||||
|
other: 重新打开
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -35,9 +46,9 @@ backend:
|
||||||
error:
|
error:
|
||||||
admin:
|
admin:
|
||||||
cannot_update_their_password:
|
cannot_update_their_password:
|
||||||
other: You cannot modify your password.
|
other: 您无法修改自己的密码。
|
||||||
cannot_modify_self_status:
|
cannot_modify_self_status:
|
||||||
other: You cannot modify your status.
|
other: 您无法修改自己的状态。
|
||||||
email_or_password_wrong:
|
email_or_password_wrong:
|
||||||
other: 邮箱和密码不匹配。
|
other: 邮箱和密码不匹配。
|
||||||
answer:
|
answer:
|
||||||
|
@ -48,7 +59,7 @@ backend:
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: 没有更新权限。
|
other: 没有更新权限。
|
||||||
question_closed_cannot_add:
|
question_closed_cannot_add:
|
||||||
other: 问题已关闭不可以新增回答
|
other: 问题已关闭,无法添加。
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: 不允许编辑评论。
|
other: 不允许编辑评论。
|
||||||
|
@ -87,7 +98,7 @@ backend:
|
||||||
other: 新密码与之前的设置相同
|
other: 新密码与之前的设置相同
|
||||||
question:
|
question:
|
||||||
already_deleted:
|
already_deleted:
|
||||||
other: This post has been deleted.
|
other: 此问题已被删除.
|
||||||
not_found:
|
not_found:
|
||||||
other: 问题未找到
|
other: 问题未找到
|
||||||
cannot_deleted:
|
cannot_deleted:
|
||||||
|
@ -99,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: 级别不符合条件
|
other: 级别不符合条件
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: 感谢您的投票。您至少需要{{ rank }}声望才能投票。
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: 报告处理失败
|
other: 报告处理失败
|
||||||
not_found:
|
not_found:
|
||||||
other: 报告未找到
|
other: 报告未找到
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: 标签已存在。
|
||||||
not_found:
|
not_found:
|
||||||
other: 标签未找到
|
other: 标签未找到
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -263,6 +278,7 @@ ui:
|
||||||
tag: 标签
|
tag: 标签
|
||||||
tags: 标签
|
tags: 标签
|
||||||
tag_wiki: 标签 wiki
|
tag_wiki: 标签 wiki
|
||||||
|
create_tag: 创建标签
|
||||||
edit_tag: 编辑标签
|
edit_tag: 编辑标签
|
||||||
ask_a_question: 提问题
|
ask_a_question: 提问题
|
||||||
edit_question: 编辑问题
|
edit_question: 编辑问题
|
||||||
|
@ -283,6 +299,9 @@ ui:
|
||||||
upgrade: Answer 升级
|
upgrade: Answer 升级
|
||||||
maintenance: 网站维护
|
maintenance: 网站维护
|
||||||
users: 用户
|
users: 用户
|
||||||
|
http_404: HTTP 错误 404
|
||||||
|
http_50X: HTTP 错误 500
|
||||||
|
http_403: HTTP 错误 403
|
||||||
notifications:
|
notifications:
|
||||||
title: 通知
|
title: 通知
|
||||||
inbox: 收件箱
|
inbox: 收件箱
|
||||||
|
@ -426,7 +445,7 @@ ui:
|
||||||
range: 显示名称不能超过 35 个字符。
|
range: 显示名称不能超过 35 个字符。
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL 固定链接
|
label: URL 固定链接
|
||||||
desc: '必须由 "a-z", "0-9", "+ # - ." 组成'
|
desc: URL 地址不能超过 35 个字符。
|
||||||
msg:
|
msg:
|
||||||
empty: URL 固定链接不能为空。
|
empty: URL 固定链接不能为空。
|
||||||
range: URL 固定链接不能超过 35 个字符。
|
range: URL 固定链接不能超过 35 个字符。
|
||||||
|
@ -435,6 +454,7 @@ ui:
|
||||||
label: 描述
|
label: 描述
|
||||||
btn_cancel: 取消
|
btn_cancel: 取消
|
||||||
btn_submit: 提交
|
btn_submit: 提交
|
||||||
|
btn_post: 发布新标签
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: 创建于
|
created_at: 创建于
|
||||||
edited_at: 编辑于
|
edited_at: 编辑于
|
||||||
|
@ -499,6 +519,7 @@ ui:
|
||||||
使用评论提问更多信息或者提出改进意见。尽量避免使用评论功能回答问题。
|
使用评论提问更多信息或者提出改进意见。尽量避免使用评论功能回答问题。
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
使用评论对回答者进行回复,或者通知回答者你已更新了问题的内容。如果要补充或者完善问题的内容,请在原问题中更改。
|
使用评论对回答者进行回复,或者通知回答者你已更新了问题的内容。如果要补充或者完善问题的内容,请在原问题中更改。
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: 编辑回答
|
title: 编辑回答
|
||||||
default_reason: 编辑回答
|
default_reason: 编辑回答
|
||||||
|
@ -584,7 +605,7 @@ ui:
|
||||||
placeholder: 搜索
|
placeholder: 搜索
|
||||||
footer:
|
footer:
|
||||||
build_on: >-
|
build_on: >-
|
||||||
基于<1>Answer</1>--为问答社区提供动力的开源软件。<br />Made with love © {{cc}}.
|
基于 <1>Answer</1> - 为问答社区提供动力的开源软件。<br />Made with love © {{cc}}.
|
||||||
upload_img:
|
upload_img:
|
||||||
name: 更改图片
|
name: 更改图片
|
||||||
loading: 加载中...
|
loading: 加载中...
|
||||||
|
@ -748,6 +769,11 @@ ui:
|
||||||
answered: 回答于
|
answered: 回答于
|
||||||
closed_in: 关闭于
|
closed_in: 关闭于
|
||||||
show_exist: 查看相关问题。
|
show_exist: 查看相关问题。
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: 个回答
|
title: 个回答
|
||||||
score: 评分
|
score: 评分
|
||||||
|
@ -764,7 +790,14 @@ ui:
|
||||||
<p>您确定要提交一个新的回答吗?</p><p>您可以直接编辑和改善您之前的回答的。</p>
|
<p>您确定要提交一个新的回答吗?</p><p>您可以直接编辑和改善您之前的回答的。</p>
|
||||||
empty: 回答内容不能为空。
|
empty: 回答内容不能为空。
|
||||||
characters: 内容长度至少 6 个字符
|
characters: 内容长度至少 6 个字符
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: 重新打开
|
||||||
title: 重新打开这个帖子
|
title: 重新打开这个帖子
|
||||||
content: 确定要重新打开吗?
|
content: 确定要重新打开吗?
|
||||||
success: 这个帖子已被重新打开
|
success: 这个帖子已被重新打开
|
||||||
|
@ -790,7 +823,7 @@ ui:
|
||||||
approve: 批准
|
approve: 批准
|
||||||
reject: 拒绝
|
reject: 拒绝
|
||||||
skip: 略过
|
skip: 略过
|
||||||
discard_draft: Discard draft
|
discard_draft: 丢弃草稿
|
||||||
search:
|
search:
|
||||||
title: 搜索结果
|
title: 搜索结果
|
||||||
keywords: 关键词
|
keywords: 关键词
|
||||||
|
@ -927,7 +960,7 @@ ui:
|
||||||
title: 创建 config.yaml
|
title: 创建 config.yaml
|
||||||
label: 已创建 config.yaml 文件。
|
label: 已创建 config.yaml 文件。
|
||||||
desc: >-
|
desc: >-
|
||||||
您可以手动在 <1>/var/wwww/xxx/</1> 目录中创建<1>config.yaml</1> 文件并粘贴以下文本。
|
您可以手动在 <1>/var/wwww/xxx/</1> 目录中创建 <1>config.yaml</1> 文件并粘贴以下文本。
|
||||||
info: 完成后,点击“下一步”按钮。
|
info: 完成后,点击“下一步”按钮。
|
||||||
site_information: 站点信息
|
site_information: 站点信息
|
||||||
admin_account: 管理员账户
|
admin_account: 管理员账户
|
||||||
|
@ -966,8 +999,8 @@ ui:
|
||||||
good_luck: "玩得愉快,祝您好运!"
|
good_luck: "玩得愉快,祝您好运!"
|
||||||
warn_title: 警告
|
warn_title: 警告
|
||||||
warn_desc: >-
|
warn_desc: >-
|
||||||
文件<1>config.yaml</1>已存在。如果您需要重置此文件中的任何配置项,请先删除它。
|
文件 <1>config.yaml</1> 已存在。如果您需要重置此文件中的任何配置项,请先删除它。
|
||||||
install_now: 您可以尝试<1>现在安装</1>。
|
install_now: 您可以尝试 <1>现在安装</1>。
|
||||||
installed: 已安裝
|
installed: 已安裝
|
||||||
installed_desc: >-
|
installed_desc: >-
|
||||||
您似乎已经安装过了。要重新安装,请先清除旧的数据库表。
|
您似乎已经安装过了。要重新安装,请先清除旧的数据库表。
|
||||||
|
@ -981,10 +1014,10 @@ ui:
|
||||||
accepted: 已被采纳
|
accepted: 已被采纳
|
||||||
page_error:
|
page_error:
|
||||||
http_error: HTTP Error {{ code }}
|
http_error: HTTP Error {{ code }}
|
||||||
desc_403: 你无权访问此页面。
|
desc_403: You don’t have permission to access this page.
|
||||||
desc_404: 很抱歉,此页面不存在。
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
desc_50X: 服务器遇到了一个错误,无法完成你的请求。
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
back_home: 回到主页
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "我们正在进行维护,我们将很快回来。"
|
desc: "我们正在进行维护,我们将很快回来。"
|
||||||
nav_menus:
|
nav_menus:
|
||||||
|
@ -1181,7 +1214,7 @@ ui:
|
||||||
msg: 简短网站描述不能为空。
|
msg: 简短网站描述不能为空。
|
||||||
text: "简短的标语,作为网站主页的标题(Html 的 title 标签)。"
|
text: "简短的标语,作为网站主页的标题(Html 的 title 标签)。"
|
||||||
desc:
|
desc:
|
||||||
label: 站点描述
|
label: 网站介绍
|
||||||
msg: 网站描述不能为空。
|
msg: 网站描述不能为空。
|
||||||
text: "使用一句话描述本站,作为网站的描述(Html 的 meta 标签)。"
|
text: "使用一句话描述本站,作为网站的描述(Html 的 meta 标签)。"
|
||||||
contact_email:
|
contact_email:
|
||||||
|
@ -1199,6 +1232,9 @@ ui:
|
||||||
label: 时区
|
label: 时区
|
||||||
msg: 时区不能为空。
|
msg: 时区不能为空。
|
||||||
text: 选择一个与您相同时区的城市。
|
text: 选择一个与您相同时区的城市。
|
||||||
|
avatar:
|
||||||
|
label: 默认头像
|
||||||
|
text: 没有自定义头像的用户。
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1364,8 +1400,8 @@ ui:
|
||||||
no_data: "空空如也"
|
no_data: "空空如也"
|
||||||
users:
|
users:
|
||||||
title: 用户
|
title: 用户
|
||||||
users_with_the_most_reputation: 本周信誉积分最高的用户
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: 本周投票最多的用户
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: 我们的社区工作人员
|
staffs: 我们的社区工作人员
|
||||||
reputation: 声望值
|
reputation: 声望值
|
||||||
votes: 投票
|
votes: 投票
|
||||||
|
@ -1373,7 +1409,7 @@ ui:
|
||||||
leave_page: 确定要离开此页面?
|
leave_page: 确定要离开此页面?
|
||||||
changes_not_save: 您的更改尚未保存
|
changes_not_save: 您的更改尚未保存
|
||||||
draft:
|
draft:
|
||||||
discard_confirm: Are you sure you want to discard your draft?
|
discard_confirm: 您确定要丢弃您的草稿吗?
|
||||||
messages:
|
messages:
|
||||||
post_deleted: This post has been deleted.
|
post_deleted: 该帖子已被删除。
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,17 @@ backend:
|
||||||
other: 未授權。
|
other: 未授權。
|
||||||
database_error:
|
database_error:
|
||||||
other: 資料庫錯誤。
|
other: 資料庫錯誤。
|
||||||
|
action:
|
||||||
|
report:
|
||||||
|
other: Flag
|
||||||
|
edit:
|
||||||
|
other: Edit
|
||||||
|
delete:
|
||||||
|
other: Delete
|
||||||
|
close:
|
||||||
|
other: Close
|
||||||
|
reopen:
|
||||||
|
other: Reopen
|
||||||
role:
|
role:
|
||||||
name:
|
name:
|
||||||
user:
|
user:
|
||||||
|
@ -47,6 +58,8 @@ backend:
|
||||||
other: 沒有刪除權限。
|
other: 沒有刪除權限。
|
||||||
cannot_update:
|
cannot_update:
|
||||||
other: 沒有更新權限。
|
other: 沒有更新權限。
|
||||||
|
question_closed_cannot_add:
|
||||||
|
other: Questions are closed and cannot be added.
|
||||||
comment:
|
comment:
|
||||||
edit_without_permission:
|
edit_without_permission:
|
||||||
other: 不允許編輯評論。
|
other: 不允許編輯評論。
|
||||||
|
@ -97,12 +110,16 @@ backend:
|
||||||
rank:
|
rank:
|
||||||
fail_to_meet_the_condition:
|
fail_to_meet_the_condition:
|
||||||
other: 級別不符合條件
|
other: 級別不符合條件
|
||||||
|
vote_fail_to_meet_the_condition:
|
||||||
|
other: Thanks for the feedback. You need at least {{ rank }} reputation to cast a vote.
|
||||||
report:
|
report:
|
||||||
handle_failed:
|
handle_failed:
|
||||||
other: 報告處理失敗。
|
other: 報告處理失敗。
|
||||||
not_found:
|
not_found:
|
||||||
other: 找不到報告。
|
other: 找不到報告。
|
||||||
tag:
|
tag:
|
||||||
|
already_exist:
|
||||||
|
other: Tag already exists.
|
||||||
not_found:
|
not_found:
|
||||||
other: 找不到標籤。
|
other: 找不到標籤。
|
||||||
recommend_tag_not_found:
|
recommend_tag_not_found:
|
||||||
|
@ -261,6 +278,7 @@ ui:
|
||||||
tag: 標籤
|
tag: 標籤
|
||||||
tags: 標籤
|
tags: 標籤
|
||||||
tag_wiki: 標籤 wiki
|
tag_wiki: 標籤 wiki
|
||||||
|
create_tag: Create Tag
|
||||||
edit_tag: 編輯標籤
|
edit_tag: 編輯標籤
|
||||||
ask_a_question: 提問題
|
ask_a_question: 提問題
|
||||||
edit_question: 編輯問題
|
edit_question: 編輯問題
|
||||||
|
@ -281,6 +299,9 @@ ui:
|
||||||
upgrade: Answer 升級
|
upgrade: Answer 升級
|
||||||
maintenance: 網站維護
|
maintenance: 網站維護
|
||||||
users: 用戶
|
users: 用戶
|
||||||
|
http_404: HTTP Error 404
|
||||||
|
http_50X: HTTP Error 500
|
||||||
|
http_403: HTTP Error 403
|
||||||
notifications:
|
notifications:
|
||||||
title: 通知
|
title: 通知
|
||||||
inbox: 收件夾
|
inbox: 收件夾
|
||||||
|
@ -424,7 +445,7 @@ ui:
|
||||||
range: 顯示名稱不能超過 35 個字符。
|
range: 顯示名稱不能超過 35 個字符。
|
||||||
slug_name:
|
slug_name:
|
||||||
label: URL 固定連結
|
label: URL 固定連結
|
||||||
desc: '必須由 "a-z", "0-9", "+ # - ." 組成'
|
desc: URL slug up to 35 characters.
|
||||||
msg:
|
msg:
|
||||||
empty: URL 固定連結不能為空。
|
empty: URL 固定連結不能為空。
|
||||||
range: URL 固定連結不能超過 35 個字元。
|
range: URL 固定連結不能超過 35 個字元。
|
||||||
|
@ -433,6 +454,7 @@ ui:
|
||||||
label: 描述
|
label: 描述
|
||||||
btn_cancel: 取消
|
btn_cancel: 取消
|
||||||
btn_submit: 提交
|
btn_submit: 提交
|
||||||
|
btn_post: Post new tag
|
||||||
tag_info:
|
tag_info:
|
||||||
created_at: 創建於
|
created_at: 創建於
|
||||||
edited_at: 編輯於
|
edited_at: 編輯於
|
||||||
|
@ -497,6 +519,7 @@ ui:
|
||||||
通过評論询问更多问题或提出改進建議。避免在評論中回答問題。
|
通过評論询问更多问题或提出改進建議。避免在評論中回答問題。
|
||||||
tip_answer: >-
|
tip_answer: >-
|
||||||
使用評論回復其他用戶或通知他們进行更改。如果你要添加新的信息,請編輯你的帖子,而不是發表評論。
|
使用評論回復其他用戶或通知他們进行更改。如果你要添加新的信息,請編輯你的帖子,而不是發表評論。
|
||||||
|
tip_vote: It adds something useful to the post
|
||||||
edit_answer:
|
edit_answer:
|
||||||
title: 編輯回答
|
title: 編輯回答
|
||||||
default_reason: 編輯回答
|
default_reason: 編輯回答
|
||||||
|
@ -746,6 +769,11 @@ ui:
|
||||||
answered: 回答於
|
answered: 回答於
|
||||||
closed_in: 關閉於
|
closed_in: 關閉於
|
||||||
show_exist: 顯示現有問題。
|
show_exist: 顯示現有問題。
|
||||||
|
useful: Useful
|
||||||
|
question_useful: It is useful and clear
|
||||||
|
question_un_useful: It is unclear or not useful
|
||||||
|
answer_useful: It is useful
|
||||||
|
answer_un_useful: It is not useful
|
||||||
answers:
|
answers:
|
||||||
title: 個回答
|
title: 個回答
|
||||||
score: 評分
|
score: 評分
|
||||||
|
@ -762,7 +790,14 @@ ui:
|
||||||
<p>您確定要添加一個新的回答嗎?</p><p>您可以使用编辑链接来完善和改进您现有的答案。</p>
|
<p>您確定要添加一個新的回答嗎?</p><p>您可以使用编辑链接来完善和改进您现有的答案。</p>
|
||||||
empty: 回答內容不能為空。
|
empty: 回答內容不能為空。
|
||||||
characters: 內容必須至少6個字元長度。
|
characters: 內容必須至少6個字元長度。
|
||||||
|
tips:
|
||||||
|
header_1: Thanks for your answer
|
||||||
|
li1_1: Please be sure to <strong>answer the question</strong>. Provide details and share your research.
|
||||||
|
li1_2: Back up any statements you make with references or personal experience.
|
||||||
|
header_2: But <strong>avoid</strong> ...
|
||||||
|
li2_1: Asking for help, seeking clarification, or responding to other answers.
|
||||||
reopen:
|
reopen:
|
||||||
|
confirm_btn: Reopen
|
||||||
title: 重新打開這個貼文
|
title: 重新打開這個貼文
|
||||||
content: 確定要重新打開嗎?
|
content: 確定要重新打開嗎?
|
||||||
success: 這個貼文已被重新打開
|
success: 這個貼文已被重新打開
|
||||||
|
@ -979,10 +1014,10 @@ ui:
|
||||||
accepted: 已採納
|
accepted: 已採納
|
||||||
page_error:
|
page_error:
|
||||||
http_error: HTTP Error {{ code }}
|
http_error: HTTP Error {{ code }}
|
||||||
desc_403: 你无权访问此頁面。
|
desc_403: You don’t have permission to access this page.
|
||||||
desc_404: 很抱歉,此頁面不存在。
|
desc_404: Unfortunately, this page doesn't exist.
|
||||||
desc_50X: 伺服器遇到了一個錯誤,無法完成你的請求。
|
desc_50X: The server encountered an error and could not complete your request.
|
||||||
back_home: 回到首頁
|
back_home: Back to homepage
|
||||||
page_maintenance:
|
page_maintenance:
|
||||||
desc: "我們正在維護中,很快就會回來。"
|
desc: "我們正在維護中,很快就會回來。"
|
||||||
nav_menus:
|
nav_menus:
|
||||||
|
@ -1196,6 +1231,9 @@ ui:
|
||||||
label: 時區
|
label: 時區
|
||||||
msg: 時區不能為空。
|
msg: 時區不能為空。
|
||||||
text: 選擇一個與您相同時區的城市。
|
text: 選擇一個與您相同時區的城市。
|
||||||
|
avatar:
|
||||||
|
label: Default Avatar
|
||||||
|
text: For users without a custom avatar of their own.
|
||||||
smtp:
|
smtp:
|
||||||
page_title: SMTP
|
page_title: SMTP
|
||||||
from_email:
|
from_email:
|
||||||
|
@ -1361,8 +1399,8 @@ ui:
|
||||||
no_data: "我們找不到任何東西。"
|
no_data: "我們找不到任何東西。"
|
||||||
users:
|
users:
|
||||||
title: 用戶
|
title: 用戶
|
||||||
users_with_the_most_reputation: 信譽積分最高的用戶
|
users_with_the_most_reputation: Users with the highest reputation scores this week
|
||||||
users_with_the_most_vote: 投票最多的用戶
|
users_with_the_most_vote: Users who voted the most this week
|
||||||
staffs: 我們的社區工作人員
|
staffs: 我們的社區工作人員
|
||||||
reputation: 聲望值
|
reputation: 聲望值
|
||||||
votes: 選票
|
votes: 選票
|
||||||
|
|
|
@ -31,6 +31,7 @@ const (
|
||||||
// key equal database's table name
|
// key equal database's table name
|
||||||
var (
|
var (
|
||||||
Version string = ""
|
Version string = ""
|
||||||
|
Revision string = ""
|
||||||
|
|
||||||
PathIgnoreMap map[string]bool
|
PathIgnoreMap map[string]bool
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package handler
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/constant"
|
"github.com/answerdev/answer/internal/base/constant"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
|
@ -73,3 +74,10 @@ func BindAndCheckReturnErr(ctx *gin.Context, data interface{}) (errFields []*val
|
||||||
errFields, _ = validator.GetValidatorByLang(lang).Check(data)
|
errFields, _ = validator.GetValidatorByLang(lang).Check(data)
|
||||||
return errFields
|
return errFields
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MsgWithParameter(msg string, list map[string]string) string {
|
||||||
|
for k, v := range list {
|
||||||
|
msg = strings.Replace(msg, "{{ "+k+" }}", v, -1)
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ func (am *AuthUserMiddleware) AdminAuth() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
userInfo, err := am.authService.GetAdminUserCacheInfo(ctx, token)
|
userInfo, err := am.authService.GetAdminUserCacheInfo(ctx, token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handler.HandleResponse(ctx, errors.Unauthorized(reason.UnauthorizedError), nil)
|
handler.HandleResponse(ctx, errors.Forbidden(reason.UnauthorizedError), nil)
|
||||||
ctx.Abort()
|
ctx.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ const (
|
||||||
TagIsUsedCannotDelete = "error.tag.is_used_cannot_delete"
|
TagIsUsedCannotDelete = "error.tag.is_used_cannot_delete"
|
||||||
TagAlreadyExist = "error.tag.already_exist"
|
TagAlreadyExist = "error.tag.already_exist"
|
||||||
RankFailToMeetTheCondition = "error.rank.fail_to_meet_the_condition"
|
RankFailToMeetTheCondition = "error.rank.fail_to_meet_the_condition"
|
||||||
|
VoteRankFailToMeetTheCondition = "error.rank.vote_fail_to_meet_the_condition"
|
||||||
ThemeNotFound = "error.theme.not_found"
|
ThemeNotFound = "error.theme.not_found"
|
||||||
LangNotFound = "error.lang.not_found"
|
LangNotFound = "error.lang.not_found"
|
||||||
ReportHandleFailed = "error.report.handle_failed"
|
ReportHandleFailed = "error.report.handle_failed"
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/translator"
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
|
"github.com/answerdev/answer/internal/controller"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
"github.com/answerdev/answer/pkg/converter"
|
"github.com/answerdev/answer/pkg/converter"
|
||||||
"github.com/answerdev/answer/pkg/day"
|
"github.com/answerdev/answer/pkg/day"
|
||||||
|
@ -41,6 +42,9 @@ var funcMap = template.FuncMap{
|
||||||
"templateHTML": func(data string) template.HTML {
|
"templateHTML": func(data string) template.HTML {
|
||||||
return template.HTML(data)
|
return template.HTML(data)
|
||||||
},
|
},
|
||||||
|
"formatLinkNofollow": func(data string) template.HTML {
|
||||||
|
return template.HTML(FormatLinkNofollow(data))
|
||||||
|
},
|
||||||
"translator": func(la i18n.Language, data string, params ...interface{}) string {
|
"translator": func(la i18n.Language, data string, params ...interface{}) string {
|
||||||
trans := translator.GlobalTrans.Tr(la, data)
|
trans := translator.GlobalTrans.Tr(la, data)
|
||||||
|
|
||||||
|
@ -116,3 +120,21 @@ var funcMap = template.FuncMap{
|
||||||
return htmltext.UrlTitle(title)
|
return htmltext.UrlTitle(title)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FormatLinkNofollow(html string) string {
|
||||||
|
var hrefRegexp = regexp.MustCompile("(?m)<a.*?[^<]>.*?</a>")
|
||||||
|
match := hrefRegexp.FindAllString(html, -1)
|
||||||
|
if match != nil {
|
||||||
|
for _, v := range match {
|
||||||
|
hasNofollow := strings.Contains(v, "rel=\"nofollow\"")
|
||||||
|
hasSiteUrl := strings.Contains(v, controller.SiteUrl)
|
||||||
|
if !hasSiteUrl {
|
||||||
|
if !hasNofollow {
|
||||||
|
nofollowUrl := strings.Replace(v, "<a", "<a rel=\"nofollow\"", 1)
|
||||||
|
html = strings.Replace(html, v, nofollowUrl, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ func (ac *AnswerController) RemoveAnswer(ctx *gin.Context) {
|
||||||
// @Success 200 {string} string ""
|
// @Success 200 {string} string ""
|
||||||
func (ac *AnswerController) Get(ctx *gin.Context) {
|
func (ac *AnswerController) Get(ctx *gin.Context) {
|
||||||
id := ctx.Query("id")
|
id := ctx.Query("id")
|
||||||
|
id = uid.DeShortID(id)
|
||||||
userID := middleware.GetLoginUserIDFromContext(ctx)
|
userID := middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
|
||||||
info, questionInfo, has, err := ac.answerService.Get(ctx, id, userID)
|
info, questionInfo, has, err := ac.answerService.Get(ctx, id, userID)
|
||||||
|
@ -137,7 +138,6 @@ func (ac *AnswerController) Add(ctx *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !has {
|
if !has {
|
||||||
// todo !has
|
|
||||||
handler.HandleResponse(ctx, nil, nil)
|
handler.HandleResponse(ctx, nil, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,7 @@ func (ac *AnswerController) Update(ctx *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
req.QuestionID = uid.DeShortID(req.QuestionID)
|
||||||
|
|
||||||
canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
||||||
permission.AnswerEdit,
|
permission.AnswerEdit,
|
||||||
|
@ -232,6 +233,7 @@ func (ac *AnswerController) AnswerList(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
req.QuestionID = uid.DeShortID(req.QuestionID)
|
||||||
|
|
||||||
canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
canList, err := ac.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
||||||
permission.AnswerEdit,
|
permission.AnswerEdit,
|
||||||
|
@ -272,6 +274,8 @@ func (ac *AnswerController) Accepted(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
req.AnswerID = uid.DeShortID(req.AnswerID)
|
||||||
|
req.QuestionID = uid.DeShortID(req.QuestionID)
|
||||||
can, err := ac.rankService.CheckOperationPermission(ctx, req.UserID, permission.AnswerAccept, req.QuestionID)
|
can, err := ac.rankService.CheckOperationPermission(ctx, req.UserID, permission.AnswerAccept, req.QuestionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
|
@ -301,6 +305,7 @@ func (ac *AnswerController) AdminSetAnswerStatus(ctx *gin.Context) {
|
||||||
if handler.BindAndCheck(ctx, req) {
|
if handler.BindAndCheck(ctx, req) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
req.AnswerID = uid.DeShortID(req.AnswerID)
|
||||||
|
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,28 @@ import (
|
||||||
"github.com/answerdev/answer/pkg/converter"
|
"github.com/answerdev/answer/pkg/converter"
|
||||||
"github.com/answerdev/answer/pkg/uid"
|
"github.com/answerdev/answer/pkg/uid"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// QuestionController question controller
|
// QuestionController question controller
|
||||||
type QuestionController struct {
|
type QuestionController struct {
|
||||||
questionService *service.QuestionService
|
questionService *service.QuestionService
|
||||||
|
answerService *service.AnswerService
|
||||||
rankService *rank.RankService
|
rankService *rank.RankService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQuestionController new controller
|
// NewQuestionController new controller
|
||||||
func NewQuestionController(questionService *service.QuestionService, rankService *rank.RankService) *QuestionController {
|
func NewQuestionController(
|
||||||
return &QuestionController{questionService: questionService, rankService: rankService}
|
questionService *service.QuestionService,
|
||||||
|
answerService *service.AnswerService,
|
||||||
|
rankService *rank.RankService,
|
||||||
|
) *QuestionController {
|
||||||
|
return &QuestionController{
|
||||||
|
questionService: questionService,
|
||||||
|
answerService: answerService,
|
||||||
|
rankService: rankService,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveQuestion delete question
|
// RemoveQuestion delete question
|
||||||
|
@ -159,6 +169,7 @@ func (qc *QuestionController) GetQuestion(ctx *gin.Context) {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
info.ID = uid.EnShortID(info.ID)
|
||||||
handler.HandleResponse(ctx, nil, info)
|
handler.HandleResponse(ctx, nil, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,6 +291,109 @@ func (qc *QuestionController) AddQuestion(ctx *gin.Context) {
|
||||||
handler.HandleResponse(ctx, err, resp)
|
handler.HandleResponse(ctx, err, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddQuestionByAnswer add question
|
||||||
|
// @Summary add question and answer
|
||||||
|
// @Description add question and answer
|
||||||
|
// @Tags Question
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Security ApiKeyAuth
|
||||||
|
// @Param data body schema.QuestionAddByAnswer true "question"
|
||||||
|
// @Success 200 {object} handler.RespBody
|
||||||
|
// @Router /answer/api/v1/question/answer [post]
|
||||||
|
func (qc *QuestionController) AddQuestionByAnswer(ctx *gin.Context) {
|
||||||
|
req := &schema.QuestionAddByAnswer{}
|
||||||
|
errFields := handler.BindAndCheckReturnErr(ctx, req)
|
||||||
|
if ctx.IsAborted() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
|
||||||
|
canList, err := qc.rankService.CheckOperationPermissions(ctx, req.UserID, []string{
|
||||||
|
permission.QuestionAdd,
|
||||||
|
permission.QuestionEdit,
|
||||||
|
permission.QuestionDelete,
|
||||||
|
permission.QuestionClose,
|
||||||
|
permission.QuestionReopen,
|
||||||
|
permission.TagUseReservedTag,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
handler.HandleResponse(ctx, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.CanAdd = canList[0]
|
||||||
|
req.CanEdit = canList[1]
|
||||||
|
req.CanDelete = canList[2]
|
||||||
|
req.CanClose = canList[3]
|
||||||
|
req.CanReopen = canList[4]
|
||||||
|
req.CanUseReservedTag = canList[5]
|
||||||
|
if !req.CanAdd {
|
||||||
|
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
questionReq := new(schema.QuestionAdd)
|
||||||
|
err = copier.Copy(questionReq, req)
|
||||||
|
if err != nil {
|
||||||
|
handler.HandleResponse(ctx, errors.Forbidden(reason.RequestFormatError), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
errList, err := qc.questionService.CheckAddQuestion(ctx, questionReq)
|
||||||
|
if err != nil {
|
||||||
|
errlist, ok := errList.([]*validator.FormErrorField)
|
||||||
|
if ok {
|
||||||
|
errFields = append(errFields, errlist...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errFields) > 0 {
|
||||||
|
handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), errFields)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := qc.questionService.AddQuestion(ctx, questionReq)
|
||||||
|
if err != nil {
|
||||||
|
errlist, ok := resp.([]*validator.FormErrorField)
|
||||||
|
if ok {
|
||||||
|
errFields = append(errFields, errlist...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errFields) > 0 {
|
||||||
|
handler.HandleResponse(ctx, errors.BadRequest(reason.RequestFormatError), errFields)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//add the question id to the answer
|
||||||
|
questionInfo, ok := resp.(*schema.QuestionInfo)
|
||||||
|
if ok {
|
||||||
|
answerReq := &schema.AnswerAddReq{}
|
||||||
|
answerReq.QuestionID = uid.DeShortID(questionInfo.ID)
|
||||||
|
answerReq.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
|
answerReq.Content = req.AnswerContent
|
||||||
|
answerReq.HTML = req.AnswerHTML
|
||||||
|
answerID, err := qc.answerService.Insert(ctx, answerReq)
|
||||||
|
if err != nil {
|
||||||
|
handler.HandleResponse(ctx, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
info, questionInfo, has, err := qc.answerService.Get(ctx, answerID, req.UserID)
|
||||||
|
if err != nil {
|
||||||
|
handler.HandleResponse(ctx, err, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
handler.HandleResponse(ctx, nil, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handler.HandleResponse(ctx, err, gin.H{
|
||||||
|
"info": info,
|
||||||
|
"question": questionInfo,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.HandleResponse(ctx, err, resp)
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateQuestion update question
|
// UpdateQuestion update question
|
||||||
// @Summary update question
|
// @Summary update question
|
||||||
// @Description update question
|
// @Description update question
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/answerdev/answer/internal/base/handler"
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
"github.com/answerdev/answer/internal/base/middleware"
|
"github.com/answerdev/answer/internal/base/middleware"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
|
"github.com/answerdev/answer/internal/entity"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
"github.com/answerdev/answer/internal/service"
|
"github.com/answerdev/answer/internal/service"
|
||||||
"github.com/answerdev/answer/internal/service/permission"
|
"github.com/answerdev/answer/internal/service/permission"
|
||||||
|
@ -52,7 +53,13 @@ func (rc *RevisionController) GetRevisionList(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := rc.revisionListService.GetRevisionList(ctx, req)
|
resp, err := rc.revisionListService.GetRevisionList(ctx, req)
|
||||||
handler.HandleResponse(ctx, err, resp)
|
list := make([]schema.GetRevisionResp, 0)
|
||||||
|
for _, item := range resp {
|
||||||
|
if item.Status == entity.RevisioNnormalStatus || item.Status == entity.RevisionReviewPassStatus {
|
||||||
|
list = append(list, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler.HandleResponse(ctx, err, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUnreviewedRevisionList godoc
|
// GetUnreviewedRevisionList godoc
|
||||||
|
|
|
@ -31,7 +31,7 @@ func NewSiteinfoController(siteInfoService *siteinfo_common.SiteInfoCommonServic
|
||||||
// @Router /answer/api/v1/siteinfo [get]
|
// @Router /answer/api/v1/siteinfo [get]
|
||||||
func (sc *SiteinfoController) GetSiteInfo(ctx *gin.Context) {
|
func (sc *SiteinfoController) GetSiteInfo(ctx *gin.Context) {
|
||||||
var err error
|
var err error
|
||||||
resp := &schema.SiteInfoResp{Version: constant.Version}
|
resp := &schema.SiteInfoResp{Version: constant.Version, Revision: constant.Revision}
|
||||||
resp.General, err = sc.siteInfoService.GetSiteGeneral(ctx)
|
resp.General, err = sc.siteInfoService.GetSiteGeneral(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
@ -103,6 +103,7 @@ func (sc *SiteinfoController) GetManifestJson(ctx *gin.Context) {
|
||||||
resp := &schema.GetManifestJsonResp{
|
resp := &schema.GetManifestJsonResp{
|
||||||
ManifestVersion: 3,
|
ManifestVersion: 3,
|
||||||
Version: constant.Version,
|
Version: constant.Version,
|
||||||
|
Revision: constant.Revision,
|
||||||
ShortName: "Answer",
|
ShortName: "Answer",
|
||||||
Name: "Answer.dev",
|
Name: "Answer.dev",
|
||||||
Icons: map[string]string{
|
Icons: map[string]string{
|
||||||
|
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"github.com/segmentfault/pacman/log"
|
"github.com/segmentfault/pacman/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var SiteUrl = ""
|
||||||
|
|
||||||
type TemplateController struct {
|
type TemplateController struct {
|
||||||
scriptPath string
|
scriptPath string
|
||||||
cssPath string
|
cssPath string
|
||||||
|
@ -67,6 +69,7 @@ func (tc *TemplateController) SiteInfo(ctx *gin.Context) *schema.TemplateSiteInf
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
|
SiteUrl = resp.General.SiteUrl
|
||||||
resp.Interface, err = tc.siteInfoService.GetSiteInterface(ctx)
|
resp.Interface, err = tc.siteInfoService.GetSiteInterface(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
|
@ -471,6 +474,7 @@ func (tc *TemplateController) html(ctx *gin.Context, code int, tpl string, siteI
|
||||||
data["HeaderCode"] = siteInfo.CustomCssHtml.CustomHeader
|
data["HeaderCode"] = siteInfo.CustomCssHtml.CustomHeader
|
||||||
data["FooterCode"] = siteInfo.CustomCssHtml.CustomFooter
|
data["FooterCode"] = siteInfo.CustomCssHtml.CustomFooter
|
||||||
data["Version"] = constant.Version
|
data["Version"] = constant.Version
|
||||||
|
data["Revision"] = constant.Revision
|
||||||
_, ok := data["path"]
|
_, ok := data["path"]
|
||||||
if !ok {
|
if !ok {
|
||||||
data["path"] = ""
|
data["path"] = ""
|
||||||
|
|
|
@ -529,9 +529,9 @@ func (uc *UserController) UserChangeEmailVerify(ctx *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := uc.userService.UserChangeEmailVerify(ctx, req.Content)
|
resp, err := uc.userService.UserChangeEmailVerify(ctx, req.Content)
|
||||||
uc.actionService.ActionRecordDel(ctx, schema.ActionRecordTypeEmail, ctx.ClientIP())
|
uc.actionService.ActionRecordDel(ctx, schema.ActionRecordTypeEmail, ctx.ClientIP())
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserRanking get user ranking
|
// UserRanking get user ranking
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/handler"
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
"github.com/answerdev/answer/internal/base/middleware"
|
"github.com/answerdev/answer/internal/base/middleware"
|
||||||
"github.com/answerdev/answer/internal/base/reason"
|
"github.com/answerdev/answer/internal/base/reason"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
"github.com/answerdev/answer/internal/service"
|
"github.com/answerdev/answer/internal/service"
|
||||||
"github.com/answerdev/answer/internal/service/rank"
|
"github.com/answerdev/answer/internal/service/rank"
|
||||||
|
@ -41,13 +44,16 @@ func (vc *VoteController) VoteUp(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
req.ObjectID = uid.DeShortID(req.ObjectID)
|
req.ObjectID = uid.DeShortID(req.ObjectID)
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
can, _, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, true)
|
can, rank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !can {
|
if !can {
|
||||||
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
|
lang := handler.GetLang(ctx)
|
||||||
|
msg := translator.Tr(lang, reason.VoteRankFailToMeetTheCondition)
|
||||||
|
msg = handler.MsgWithParameter(msg, map[string]string{"rank": fmt.Sprintf("%d", rank)})
|
||||||
|
handler.HandleResponse(ctx, errors.Forbidden(reason.VoteRankFailToMeetTheCondition).WithMsg(msg), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +84,16 @@ func (vc *VoteController) VoteDown(ctx *gin.Context) {
|
||||||
}
|
}
|
||||||
req.ObjectID = uid.DeShortID(req.ObjectID)
|
req.ObjectID = uid.DeShortID(req.ObjectID)
|
||||||
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
req.UserID = middleware.GetLoginUserIDFromContext(ctx)
|
||||||
can, _, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, false)
|
can, rank, err := vc.rankService.CheckVotePermission(ctx, req.UserID, req.ObjectID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handler.HandleResponse(ctx, err, nil)
|
handler.HandleResponse(ctx, err, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !can {
|
if !can {
|
||||||
handler.HandleResponse(ctx, errors.Forbidden(reason.RankFailToMeetTheCondition), nil)
|
lang := handler.GetLang(ctx)
|
||||||
|
msg := translator.Tr(lang, reason.VoteRankFailToMeetTheCondition)
|
||||||
|
msg = handler.MsgWithParameter(msg, map[string]string{"rank": fmt.Sprintf("%d", rank)})
|
||||||
|
handler.HandleResponse(ctx, errors.Forbidden(reason.VoteRankFailToMeetTheCondition).WithMsg(msg), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// RevisioNnormalStatus this revision is Nnormal
|
||||||
|
RevisioNnormalStatus = 0
|
||||||
// RevisionUnreviewedStatus this revision is unreviewed
|
// RevisionUnreviewedStatus this revision is unreviewed
|
||||||
RevisionUnreviewedStatus = 1
|
RevisionUnreviewedStatus = 1
|
||||||
// RevisionReviewPassStatus this revision is reviewed and approved by operator
|
// RevisionReviewPassStatus this revision is reviewed and approved by operator
|
||||||
|
|
|
@ -147,8 +147,8 @@ func (ar *authRepo) AddUserTokenMapping(ctx context.Context, userID, accessToken
|
||||||
return ar.data.Cache.SetString(ctx, key, string(content), constant.UserTokenCacheTime)
|
return ar.data.Cache.SetString(ctx, key, string(content), constant.UserTokenCacheTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAllUserTokens Log out all users under this user id
|
// RemoveUserTokens Log out all users under this user id
|
||||||
func (ar *authRepo) RemoveAllUserTokens(ctx context.Context, userID string) {
|
func (ar *authRepo) RemoveUserTokens(ctx context.Context, userID string) {
|
||||||
key := constant.UserTokenMappingCacheKey + userID
|
key := constant.UserTokenMappingCacheKey + userID
|
||||||
resp, _ := ar.data.Cache.GetString(ctx, key)
|
resp, _ := ar.data.Cache.GetString(ctx, key)
|
||||||
mapping := make(map[string]bool, 0)
|
mapping := make(map[string]bool, 0)
|
||||||
|
|
|
@ -28,15 +28,15 @@ func NewUserRoleRelRepo(data *data.Data) role.UserRoleRelRepo {
|
||||||
func (ur *userRoleRelRepo) SaveUserRoleRel(ctx context.Context, userID string, roleID int) (err error) {
|
func (ur *userRoleRelRepo) SaveUserRoleRel(ctx context.Context, userID string, roleID int) (err error) {
|
||||||
_, err = ur.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
|
_, err = ur.data.DB.Transaction(func(session *xorm.Session) (interface{}, error) {
|
||||||
item := &entity.UserRoleRel{UserID: userID}
|
item := &entity.UserRoleRel{UserID: userID}
|
||||||
exist, err := ur.data.DB.Get(item)
|
exist, err := session.Get(item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
item.RoleID = roleID
|
item.RoleID = roleID
|
||||||
_, err = ur.data.DB.ID(item.ID).Update(item)
|
_, err = session.ID(item.ID).Update(item)
|
||||||
} else {
|
} else {
|
||||||
_, err = ur.data.DB.Insert(&entity.UserRoleRel{UserID: userID, RoleID: roleID})
|
_, err = session.Insert(&entity.UserRoleRel{UserID: userID, RoleID: roleID})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tag_common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/data"
|
"github.com/answerdev/answer/internal/base/data"
|
||||||
"github.com/answerdev/answer/internal/base/pager"
|
"github.com/answerdev/answer/internal/base/pager"
|
||||||
|
@ -45,7 +46,7 @@ func (tr *tagCommonRepo) GetTagListByIDs(ctx context.Context, ids []string) (tag
|
||||||
// GetTagBySlugName get tag by slug name
|
// GetTagBySlugName get tag by slug name
|
||||||
func (tr *tagCommonRepo) GetTagBySlugName(ctx context.Context, slugName string) (tagInfo *entity.Tag, exist bool, err error) {
|
func (tr *tagCommonRepo) GetTagBySlugName(ctx context.Context, slugName string) (tagInfo *entity.Tag, exist bool, err error) {
|
||||||
tagInfo = &entity.Tag{}
|
tagInfo = &entity.Tag{}
|
||||||
session := tr.data.DB.Where("slug_name = ?", slugName)
|
session := tr.data.DB.Where("slug_name = LOWER(?)", slugName)
|
||||||
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
||||||
exist, err = session.Get(tagInfo)
|
exist, err = session.Get(tagInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -60,7 +61,7 @@ func (tr *tagCommonRepo) GetTagListByName(ctx context.Context, name string, hasR
|
||||||
cond := &entity.Tag{}
|
cond := &entity.Tag{}
|
||||||
session := tr.data.DB.Where("")
|
session := tr.data.DB.Where("")
|
||||||
if name != "" {
|
if name != "" {
|
||||||
session.Where("slug_name LIKE ? or display_name LIKE ?", name+"%", name+"%")
|
session.Where("slug_name LIKE LOWER(?) or display_name LIKE ?", name+"%", name+"%")
|
||||||
} else {
|
} else {
|
||||||
session.UseBool("recommend")
|
session.UseBool("recommend")
|
||||||
cond.Recommend = true
|
cond.Recommend = true
|
||||||
|
@ -106,6 +107,7 @@ func (tr *tagCommonRepo) GetReservedTagList(ctx context.Context) (tagList []*ent
|
||||||
|
|
||||||
// GetTagListByNames get tag list all like name
|
// GetTagListByNames get tag list all like name
|
||||||
func (tr *tagCommonRepo) GetTagListByNames(ctx context.Context, names []string) (tagList []*entity.Tag, err error) {
|
func (tr *tagCommonRepo) GetTagListByNames(ctx context.Context, names []string) (tagList []*entity.Tag, err error) {
|
||||||
|
|
||||||
tagList = make([]*entity.Tag, 0)
|
tagList = make([]*entity.Tag, 0)
|
||||||
session := tr.data.DB.In("slug_name", names).UseBool("recommend", "reserved")
|
session := tr.data.DB.In("slug_name", names).UseBool("recommend", "reserved")
|
||||||
// session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
// session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
||||||
|
@ -140,7 +142,7 @@ func (tr *tagCommonRepo) GetTagPage(ctx context.Context, page, pageSize int, tag
|
||||||
session := tr.data.DB.NewSession()
|
session := tr.data.DB.NewSession()
|
||||||
|
|
||||||
if len(tag.SlugName) > 0 {
|
if len(tag.SlugName) > 0 {
|
||||||
session.Where(builder.Or(builder.Like{"slug_name", tag.SlugName}, builder.Like{"display_name", tag.SlugName}))
|
session.Where(builder.Or(builder.Like{"slug_name", fmt.Sprintf("LOWER(%s)", tag.SlugName)}, builder.Like{"display_name", tag.SlugName}))
|
||||||
tag.SlugName = ""
|
tag.SlugName = ""
|
||||||
}
|
}
|
||||||
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
session.Where(builder.Eq{"status": entity.TagStatusAvailable})
|
||||||
|
|
|
@ -186,6 +186,7 @@ func (a *AnswerAPIRouter) RegisterAnswerAPIRouter(r *gin.RouterGroup) {
|
||||||
|
|
||||||
// question
|
// question
|
||||||
r.POST("/question", a.questionController.AddQuestion)
|
r.POST("/question", a.questionController.AddQuestion)
|
||||||
|
r.POST("/question/answer", a.questionController.AddQuestionByAnswer)
|
||||||
r.PUT("/question", a.questionController.UpdateQuestion)
|
r.PUT("/question", a.questionController.UpdateQuestion)
|
||||||
r.DELETE("/question", a.questionController.RemoveQuestion)
|
r.DELETE("/question", a.questionController.RemoveQuestion)
|
||||||
r.PUT("/question/status", a.questionController.CloseQuestion)
|
r.PUT("/question/status", a.questionController.CloseQuestion)
|
||||||
|
|
|
@ -27,6 +27,7 @@ type DashboardInfo struct {
|
||||||
|
|
||||||
type DashboardInfoVersion struct {
|
type DashboardInfoVersion struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
Revision string `json:"revision"`
|
||||||
RemoteVersion string `json:"remote_version"`
|
RemoteVersion string `json:"remote_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,33 @@ func (req *QuestionAdd) Check() (errFields []*validator.FormErrorField, err erro
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type QuestionAddByAnswer struct {
|
||||||
|
// question title
|
||||||
|
Title string `validate:"required,notblank,gte=6,lte=150" json:"title"`
|
||||||
|
// content
|
||||||
|
Content string `validate:"required,notblank,gte=6,lte=65535" json:"content"`
|
||||||
|
// html
|
||||||
|
HTML string `json:"-"`
|
||||||
|
AnswerContent string `validate:"required,notblank,gte=6,lte=65535" json:"answer_content"`
|
||||||
|
AnswerHTML string `json:"-"`
|
||||||
|
// tags
|
||||||
|
Tags []*TagItem `validate:"required,dive" json:"tags"`
|
||||||
|
// user id
|
||||||
|
UserID string `json:"-"`
|
||||||
|
QuestionPermission
|
||||||
|
}
|
||||||
|
|
||||||
|
func (req *QuestionAddByAnswer) Check() (errFields []*validator.FormErrorField, err error) {
|
||||||
|
req.HTML = converter.Markdown2HTML(req.Content)
|
||||||
|
req.AnswerHTML = converter.Markdown2HTML(req.AnswerContent)
|
||||||
|
for _, tag := range req.Tags {
|
||||||
|
if len(tag.OriginalText) > 0 {
|
||||||
|
tag.ParsedText = converter.Markdown2HTML(tag.OriginalText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
type QuestionPermission struct {
|
type QuestionPermission struct {
|
||||||
// whether user can add it
|
// whether user can add it
|
||||||
CanAdd bool `json:"-"`
|
CanAdd bool `json:"-"`
|
||||||
|
|
|
@ -170,6 +170,7 @@ type SiteInfoResp struct {
|
||||||
CustomCssHtml *SiteCustomCssHTMLResp `json:"custom_css_html"`
|
CustomCssHtml *SiteCustomCssHTMLResp `json:"custom_css_html"`
|
||||||
SiteSeo *SiteSeoReq `json:"site_seo"`
|
SiteSeo *SiteSeoReq `json:"site_seo"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
Revision string `json:"revision"`
|
||||||
}
|
}
|
||||||
type TemplateSiteInfoResp struct {
|
type TemplateSiteInfoResp struct {
|
||||||
General *SiteGeneralResp `json:"general"`
|
General *SiteGeneralResp `json:"general"`
|
||||||
|
@ -225,6 +226,7 @@ type GetSMTPConfigResp struct {
|
||||||
type GetManifestJsonResp struct {
|
type GetManifestJsonResp struct {
|
||||||
ManifestVersion int `json:"manifest_version"`
|
ManifestVersion int `json:"manifest_version"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
Revision string `json:"revision"`
|
||||||
ShortName string `json:"short_name"`
|
ShortName string `json:"short_name"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Icons map[string]string `json:"icons"`
|
Icons map[string]string `json:"icons"`
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
usercommon "github.com/answerdev/answer/internal/service/user_common"
|
||||||
"github.com/answerdev/answer/pkg/converter"
|
"github.com/answerdev/answer/pkg/converter"
|
||||||
"github.com/answerdev/answer/pkg/obj"
|
"github.com/answerdev/answer/pkg/obj"
|
||||||
|
"github.com/answerdev/answer/pkg/uid"
|
||||||
"github.com/segmentfault/pacman/log"
|
"github.com/segmentfault/pacman/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,6 +92,10 @@ func (as *ActivityService) GetObjectTimeline(ctx context.Context, req *schema.Ge
|
||||||
item.CancelledAt = act.CancelledAt.Unix()
|
item.CancelledAt = act.CancelledAt.Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if item.ObjectType == constant.QuestionObjectType || item.ObjectType == constant.AnswerObjectType {
|
||||||
|
item.ObjectID = uid.EnShortID(act.ObjectID)
|
||||||
|
}
|
||||||
|
|
||||||
// database save activity type is number, change to activity type string is like "question.asked".
|
// database save activity type is number, change to activity type string is like "question.asked".
|
||||||
// so we need to cut the front part of '.'
|
// so we need to cut the front part of '.'
|
||||||
_, item.ActivityType, _ = strings.Cut(config.ID2KeyMapping[act.ActivityType], ".")
|
_, item.ActivityType, _ = strings.Cut(config.ID2KeyMapping[act.ActivityType], ".")
|
||||||
|
|
|
@ -326,6 +326,7 @@ func (as *AnswerService) UpdateAccepted(ctx context.Context, req *schema.AnswerA
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
newAnswerInfo.ID = uid.DeShortID(newAnswerInfo.ID)
|
||||||
if !newAnswerInfoexist {
|
if !newAnswerInfoexist {
|
||||||
return errors.BadRequest(reason.AnswerNotFound)
|
return errors.BadRequest(reason.AnswerNotFound)
|
||||||
}
|
}
|
||||||
|
@ -335,12 +336,13 @@ func (as *AnswerService) UpdateAccepted(ctx context.Context, req *schema.AnswerA
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
questionInfo.ID = uid.DeShortID(questionInfo.ID)
|
||||||
if !exist {
|
if !exist {
|
||||||
return errors.BadRequest(reason.QuestionNotFound)
|
return errors.BadRequest(reason.QuestionNotFound)
|
||||||
}
|
}
|
||||||
if questionInfo.UserID != req.UserID {
|
// if questionInfo.UserID != req.UserID {
|
||||||
return fmt.Errorf("no permission to set answer")
|
// return fmt.Errorf("no permission to set answer")
|
||||||
}
|
// }
|
||||||
if questionInfo.AcceptedAnswerID == req.AnswerID {
|
if questionInfo.AcceptedAnswerID == req.AnswerID {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -351,6 +353,7 @@ func (as *AnswerService) UpdateAccepted(ctx context.Context, req *schema.AnswerA
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
oldAnswerInfo.ID = uid.DeShortID(oldAnswerInfo.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = as.answerRepo.UpdateAccepted(ctx, req.AnswerID, req.QuestionID)
|
err = as.answerRepo.UpdateAccepted(ctx, req.AnswerID, req.QuestionID)
|
||||||
|
|
|
@ -20,7 +20,7 @@ type AuthRepo interface {
|
||||||
SetAdminUserCacheInfo(ctx context.Context, accessToken string, userInfo *entity.UserCacheInfo) error
|
SetAdminUserCacheInfo(ctx context.Context, accessToken string, userInfo *entity.UserCacheInfo) error
|
||||||
RemoveAdminUserCacheInfo(ctx context.Context, accessToken string) (err error)
|
RemoveAdminUserCacheInfo(ctx context.Context, accessToken string) (err error)
|
||||||
AddUserTokenMapping(ctx context.Context, userID, accessToken string) (err error)
|
AddUserTokenMapping(ctx context.Context, userID, accessToken string) (err error)
|
||||||
RemoveAllUserTokens(ctx context.Context, userID string)
|
RemoveUserTokens(ctx context.Context, userID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthService kit service
|
// AuthService kit service
|
||||||
|
@ -85,9 +85,9 @@ func (as *AuthService) AddUserTokenMapping(ctx context.Context, userID, accessTo
|
||||||
return as.authRepo.AddUserTokenMapping(ctx, userID, accessToken)
|
return as.authRepo.AddUserTokenMapping(ctx, userID, accessToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveAllUserTokens Log out all users under this user id
|
// RemoveUserTokens Log out all users under this user id
|
||||||
func (as *AuthService) RemoveAllUserTokens(ctx context.Context, userID string) {
|
func (as *AuthService) RemoveUserTokens(ctx context.Context, userID string) {
|
||||||
as.authRepo.RemoveAllUserTokens(ctx, userID)
|
as.authRepo.RemoveUserTokens(ctx, userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Admin
|
//Admin
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"github.com/answerdev/answer/pkg/encryption"
|
"github.com/answerdev/answer/pkg/encryption"
|
||||||
"github.com/answerdev/answer/pkg/htmltext"
|
"github.com/answerdev/answer/pkg/htmltext"
|
||||||
"github.com/answerdev/answer/pkg/uid"
|
"github.com/answerdev/answer/pkg/uid"
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
"github.com/segmentfault/pacman/log"
|
"github.com/segmentfault/pacman/log"
|
||||||
|
@ -448,7 +447,6 @@ func (cs *CommentService) GetCommentPersonalWithPage(ctx context.Context, req *s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
} else {
|
} else {
|
||||||
spew.Dump("==", objInfo)
|
|
||||||
commentResp.ObjectType = objInfo.ObjectType
|
commentResp.ObjectType = objInfo.ObjectType
|
||||||
commentResp.Title = objInfo.Title
|
commentResp.Title = objInfo.Title
|
||||||
commentResp.UrlTitle = htmltext.UrlTitle(objInfo.Title)
|
commentResp.UrlTitle = htmltext.UrlTitle(objInfo.Title)
|
||||||
|
|
|
@ -90,6 +90,7 @@ func (ds *DashboardService) StatisticalByCache(ctx context.Context) (*schema.Das
|
||||||
startTime := time.Now().Unix() - schema.AppStartTime.Unix()
|
startTime := time.Now().Unix() - schema.AppStartTime.Unix()
|
||||||
dashboardInfo.AppStartTime = fmt.Sprintf("%d", startTime)
|
dashboardInfo.AppStartTime = fmt.Sprintf("%d", startTime)
|
||||||
dashboardInfo.VersionInfo.Version = constant.Version
|
dashboardInfo.VersionInfo.Version = constant.Version
|
||||||
|
dashboardInfo.VersionInfo.Revision = constant.Revision
|
||||||
return dashboardInfo, nil
|
return dashboardInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +195,7 @@ func (ds *DashboardService) Statistical(ctx context.Context) (*schema.DashboardI
|
||||||
dashboardInfo.AppStartTime = fmt.Sprintf("%d", startTime)
|
dashboardInfo.AppStartTime = fmt.Sprintf("%d", startTime)
|
||||||
dashboardInfo.TimeZone = siteInfoInterface.TimeZone
|
dashboardInfo.TimeZone = siteInfoInterface.TimeZone
|
||||||
dashboardInfo.VersionInfo.Version = constant.Version
|
dashboardInfo.VersionInfo.Version = constant.Version
|
||||||
|
dashboardInfo.VersionInfo.Revision = constant.Revision
|
||||||
dashboardInfo.VersionInfo.RemoteVersion = ds.RemoteVersion(ctx)
|
dashboardInfo.VersionInfo.RemoteVersion = ds.RemoteVersion(ctx)
|
||||||
return dashboardInfo, nil
|
return dashboardInfo, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
questioncommon "github.com/answerdev/answer/internal/service/question_common"
|
questioncommon "github.com/answerdev/answer/internal/service/question_common"
|
||||||
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
|
tagcommon "github.com/answerdev/answer/internal/service/tag_common"
|
||||||
"github.com/answerdev/answer/pkg/obj"
|
"github.com/answerdev/answer/pkg/obj"
|
||||||
|
"github.com/answerdev/answer/pkg/uid"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ func (os *ObjService) GetUnreviewedRevisionInfo(ctx context.Context, objectID st
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
questionInfo.ID = uid.EnShortID(questionInfo.ID)
|
||||||
if !exist {
|
if !exist {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -85,6 +87,7 @@ func (os *ObjService) GetUnreviewedRevisionInfo(ctx context.Context, objectID st
|
||||||
if !exist {
|
if !exist {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
questionInfo.ID = uid.EnShortID(questionInfo.ID)
|
||||||
objInfo = &schema.UnreviewedRevisionInfoInfo{
|
objInfo = &schema.UnreviewedRevisionInfoInfo{
|
||||||
ObjectID: answerInfo.ID,
|
ObjectID: answerInfo.ID,
|
||||||
Title: questionInfo.Title,
|
Title: questionInfo.Title,
|
||||||
|
|
|
@ -3,24 +3,27 @@ package permission
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetAnswerPermission get answer permission
|
// GetAnswerPermission get answer permission
|
||||||
func GetAnswerPermission(ctx context.Context, userID string, creatorUserID string, canEdit, canDelete bool) (
|
func GetAnswerPermission(ctx context.Context, userID string, creatorUserID string, canEdit, canDelete bool) (
|
||||||
actions []*schema.PermissionMemberAction) {
|
actions []*schema.PermissionMemberAction) {
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
actions = make([]*schema.PermissionMemberAction, 0)
|
actions = make([]*schema.PermissionMemberAction, 0)
|
||||||
if len(userID) > 0 {
|
if len(userID) > 0 {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "report",
|
Action: "report",
|
||||||
Name: "Flag",
|
Name: translator.Tr(lang, reportActionName),
|
||||||
Type: "reason",
|
Type: "reason",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if canEdit || userID == creatorUserID {
|
if canEdit || userID == creatorUserID {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "edit",
|
Action: "edit",
|
||||||
Name: "Edit",
|
Name: translator.Tr(lang, editActionName),
|
||||||
Type: "edit",
|
Type: "edit",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -28,7 +31,7 @@ func GetAnswerPermission(ctx context.Context, userID string, creatorUserID strin
|
||||||
if canDelete || userID == creatorUserID {
|
if canDelete || userID == creatorUserID {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "delete",
|
Action: "delete",
|
||||||
Name: "Delete",
|
Name: translator.Tr(lang, deleteActionName),
|
||||||
Type: "confirm",
|
Type: "confirm",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,20 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/answerdev/answer/internal/base/constant"
|
"github.com/answerdev/answer/internal/base/constant"
|
||||||
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetCommentPermission get comment permission
|
// GetCommentPermission get comment permission
|
||||||
func GetCommentPermission(ctx context.Context, userID string, creatorUserID string,
|
func GetCommentPermission(ctx context.Context, userID string, creatorUserID string,
|
||||||
createdAt time.Time, canEdit, canDelete bool) (actions []*schema.PermissionMemberAction) {
|
createdAt time.Time, canEdit, canDelete bool) (actions []*schema.PermissionMemberAction) {
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
actions = make([]*schema.PermissionMemberAction, 0)
|
actions = make([]*schema.PermissionMemberAction, 0)
|
||||||
if len(userID) > 0 {
|
if len(userID) > 0 {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "report",
|
Action: "report",
|
||||||
Name: "Flag",
|
Name: translator.Tr(lang, reportActionName),
|
||||||
Type: "reason",
|
Type: "reason",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,7 +26,7 @@ func GetCommentPermission(ctx context.Context, userID string, creatorUserID stri
|
||||||
if canEdit || (userID == creatorUserID && time.Now().Before(deadline)) {
|
if canEdit || (userID == creatorUserID && time.Now().Before(deadline)) {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "edit",
|
Action: "edit",
|
||||||
Name: "Edit",
|
Name: translator.Tr(lang, editActionName),
|
||||||
Type: "edit",
|
Type: "edit",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -31,7 +34,7 @@ func GetCommentPermission(ctx context.Context, userID string, creatorUserID stri
|
||||||
if canDelete || userID == creatorUserID {
|
if canDelete || userID == creatorUserID {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "delete",
|
Action: "delete",
|
||||||
Name: "Delete",
|
Name: translator.Tr(lang, deleteActionName),
|
||||||
Type: "reason",
|
Type: "reason",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,3 +36,11 @@ const (
|
||||||
TagAudit = "tag.audit"
|
TagAudit = "tag.audit"
|
||||||
TagUseReservedTag = "tag.use_reserved_tag"
|
TagUseReservedTag = "tag.use_reserved_tag"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
reportActionName = "action.report"
|
||||||
|
editActionName = "action.edit"
|
||||||
|
deleteActionName = "action.delete"
|
||||||
|
closeActionName = "action.close"
|
||||||
|
reopenActionName = "action.reopen"
|
||||||
|
)
|
||||||
|
|
|
@ -3,6 +3,8 @@ package permission
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,39 +12,40 @@ import (
|
||||||
func GetQuestionPermission(ctx context.Context, userID string, creatorUserID string,
|
func GetQuestionPermission(ctx context.Context, userID string, creatorUserID string,
|
||||||
canEdit, canDelete, canClose, canReopen bool) (
|
canEdit, canDelete, canClose, canReopen bool) (
|
||||||
actions []*schema.PermissionMemberAction) {
|
actions []*schema.PermissionMemberAction) {
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
actions = make([]*schema.PermissionMemberAction, 0)
|
actions = make([]*schema.PermissionMemberAction, 0)
|
||||||
if len(userID) > 0 {
|
if len(userID) > 0 {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "report",
|
Action: "report",
|
||||||
Name: "Flag",
|
Name: translator.Tr(lang, reportActionName),
|
||||||
Type: "reason",
|
Type: "reason",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if canEdit || userID == creatorUserID {
|
if canEdit || userID == creatorUserID {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "edit",
|
Action: "edit",
|
||||||
Name: "Edit",
|
Name: translator.Tr(lang, editActionName),
|
||||||
Type: "edit",
|
Type: "edit",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if canClose {
|
if canClose {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "close",
|
Action: "close",
|
||||||
Name: "Close",
|
Name: translator.Tr(lang, closeActionName),
|
||||||
Type: "confirm",
|
Type: "confirm",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if canReopen {
|
if canReopen {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "reopen",
|
Action: "reopen",
|
||||||
Name: "Reopen",
|
Name: translator.Tr(lang, reopenActionName),
|
||||||
Type: "confirm",
|
Type: "confirm",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if canDelete || userID == creatorUserID {
|
if canDelete || userID == creatorUserID {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "delete",
|
Action: "delete",
|
||||||
Name: "Delete",
|
Name: translator.Tr(lang, deleteActionName),
|
||||||
Type: "confirm",
|
Type: "confirm",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,20 @@ package permission
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/answerdev/answer/internal/base/handler"
|
||||||
|
"github.com/answerdev/answer/internal/base/translator"
|
||||||
"github.com/answerdev/answer/internal/schema"
|
"github.com/answerdev/answer/internal/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetTagPermission get tag permission
|
// GetTagPermission get tag permission
|
||||||
func GetTagPermission(ctx context.Context, canEdit, canDelete bool) (
|
func GetTagPermission(ctx context.Context, canEdit, canDelete bool) (
|
||||||
actions []*schema.PermissionMemberAction) {
|
actions []*schema.PermissionMemberAction) {
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
actions = make([]*schema.PermissionMemberAction, 0)
|
actions = make([]*schema.PermissionMemberAction, 0)
|
||||||
if canEdit {
|
if canEdit {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "edit",
|
Action: "edit",
|
||||||
Name: "Edit",
|
Name: translator.Tr(lang, editActionName),
|
||||||
Type: "edit",
|
Type: "edit",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,7 +24,7 @@ func GetTagPermission(ctx context.Context, canEdit, canDelete bool) (
|
||||||
if canDelete {
|
if canDelete {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "delete",
|
Action: "delete",
|
||||||
Name: "Delete",
|
Name: translator.Tr(lang, deleteActionName),
|
||||||
Type: "reason",
|
Type: "reason",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -31,11 +34,12 @@ func GetTagPermission(ctx context.Context, canEdit, canDelete bool) (
|
||||||
// GetTagSynonymPermission get tag synonym permission
|
// GetTagSynonymPermission get tag synonym permission
|
||||||
func GetTagSynonymPermission(ctx context.Context, canEdit bool) (
|
func GetTagSynonymPermission(ctx context.Context, canEdit bool) (
|
||||||
actions []*schema.PermissionMemberAction) {
|
actions []*schema.PermissionMemberAction) {
|
||||||
|
lang := handler.GetLangByCtx(ctx)
|
||||||
actions = make([]*schema.PermissionMemberAction, 0)
|
actions = make([]*schema.PermissionMemberAction, 0)
|
||||||
if canEdit {
|
if canEdit {
|
||||||
actions = append(actions, &schema.PermissionMemberAction{
|
actions = append(actions, &schema.PermissionMemberAction{
|
||||||
Action: "edit",
|
Action: "edit",
|
||||||
Name: "Edit",
|
Name: translator.Tr(lang, editActionName),
|
||||||
Type: "edit",
|
Type: "edit",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,13 +335,16 @@ func (qs *QuestionCommon) FormatQuestionsPage(
|
||||||
} else {
|
} else {
|
||||||
item.Tags = make([]*schema.TagResp, 0)
|
item.Tags = make([]*schema.TagResp, 0)
|
||||||
}
|
}
|
||||||
userInfo := userInfoMap[item.Operator.ID]
|
userInfo, ok := userInfoMap[item.Operator.ID]
|
||||||
|
if ok {
|
||||||
if userInfo != nil {
|
if userInfo != nil {
|
||||||
item.Operator.DisplayName = userInfo.DisplayName
|
item.Operator.DisplayName = userInfo.DisplayName
|
||||||
item.Operator.Username = userInfo.Username
|
item.Operator.Username = userInfo.Username
|
||||||
item.Operator.Rank = userInfo.Rank
|
item.Operator.Rank = userInfo.Rank
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return formattedQuestions, nil
|
return formattedQuestions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,6 +417,11 @@ func (qs *QuestionCommon) RemoveQuestion(ctx context.Context, req *schema.Remove
|
||||||
if !has {
|
if !has {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if questionInfo.Status == entity.QuestionStatusDeleted {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
questionInfo.Status = entity.QuestionStatusDeleted
|
questionInfo.Status = entity.QuestionStatusDeleted
|
||||||
err = qs.questionRepo.UpdateQuestionStatus(ctx, questionInfo)
|
err = qs.questionRepo.UpdateQuestionStatus(ctx, questionInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -572,6 +572,7 @@ func (qs *QuestionService) UpdateQuestion(ctx context.Context, req *schema.Quest
|
||||||
// It's not you or the administrator that needs to be reviewed
|
// It's not you or the administrator that needs to be reviewed
|
||||||
if !canUpdate {
|
if !canUpdate {
|
||||||
revisionDTO.Status = entity.RevisionUnreviewedStatus
|
revisionDTO.Status = entity.RevisionUnreviewedStatus
|
||||||
|
revisionDTO.UserID = req.UserID //use revision userid
|
||||||
} else {
|
} else {
|
||||||
//Direct modification
|
//Direct modification
|
||||||
revisionDTO.Status = entity.RevisionReviewPassStatus
|
revisionDTO.Status = entity.RevisionReviewPassStatus
|
||||||
|
|
|
@ -85,13 +85,42 @@ func (ts *TagCommonService) SearchTagLike(ctx context.Context, req *schema.Searc
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ts.TagsFormatRecommendAndReserved(ctx, tags)
|
ts.TagsFormatRecommendAndReserved(ctx, tags)
|
||||||
|
mainTagId := make([]string, 0)
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
|
if tag.MainTagID != 0 {
|
||||||
|
mainTagId = append(mainTagId, converter.IntToString(tag.MainTagID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mainTagList, err := ts.tagCommonRepo.GetTagListByIDs(ctx, mainTagId)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mainTagMap := make(map[string]*entity.Tag)
|
||||||
|
for _, tag := range mainTagList {
|
||||||
|
mainTagMap[tag.ID] = tag
|
||||||
|
}
|
||||||
|
for _, tag := range tags {
|
||||||
|
if tag.MainTagID != 0 {
|
||||||
|
_, ok := mainTagMap[converter.IntToString(tag.MainTagID)]
|
||||||
|
if ok {
|
||||||
|
tag.SlugName = mainTagMap[converter.IntToString(tag.MainTagID)].SlugName
|
||||||
|
tag.DisplayName = mainTagMap[converter.IntToString(tag.MainTagID)].DisplayName
|
||||||
|
tag.Reserved = mainTagMap[converter.IntToString(tag.MainTagID)].Reserved
|
||||||
|
tag.Recommend = mainTagMap[converter.IntToString(tag.MainTagID)].Recommend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RepetitiveTag := make(map[string]bool)
|
||||||
|
for _, tag := range tags {
|
||||||
|
if _, ok := RepetitiveTag[tag.SlugName]; !ok {
|
||||||
item := schema.SearchTagLikeResp{}
|
item := schema.SearchTagLikeResp{}
|
||||||
item.SlugName = tag.SlugName
|
item.SlugName = tag.SlugName
|
||||||
item.DisplayName = tag.DisplayName
|
item.DisplayName = tag.DisplayName
|
||||||
item.Recommend = tag.Recommend
|
item.Recommend = tag.Recommend
|
||||||
item.Reserved = tag.Reserved
|
item.Reserved = tag.Reserved
|
||||||
resp = append(resp, item)
|
resp = append(resp, item)
|
||||||
|
RepetitiveTag[tag.SlugName] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
@ -233,8 +262,10 @@ func (ts *TagCommonService) AddTag(ctx context.Context, req *schema.AddTagReq) (
|
||||||
if exist {
|
if exist {
|
||||||
return nil, errors.BadRequest(reason.TagAlreadyExist)
|
return nil, errors.BadRequest(reason.TagAlreadyExist)
|
||||||
}
|
}
|
||||||
|
SlugName := strings.ReplaceAll(req.SlugName, " ", "-")
|
||||||
|
SlugName = strings.ToLower(SlugName)
|
||||||
tagInfo := &entity.Tag{
|
tagInfo := &entity.Tag{
|
||||||
SlugName: strings.ReplaceAll(req.SlugName, " ", "-"),
|
SlugName: SlugName,
|
||||||
DisplayName: req.DisplayName,
|
DisplayName: req.DisplayName,
|
||||||
OriginalText: req.OriginalText,
|
OriginalText: req.OriginalText,
|
||||||
ParsedText: req.ParsedText,
|
ParsedText: req.ParsedText,
|
||||||
|
@ -535,7 +566,7 @@ func (ts *TagCommonService) ObjectChangeTag(ctx context.Context, objectTagData *
|
||||||
thisObjTagNameList := make([]string, 0)
|
thisObjTagNameList := make([]string, 0)
|
||||||
thisObjTagIDList := make([]string, 0)
|
thisObjTagIDList := make([]string, 0)
|
||||||
for _, t := range objectTagData.Tags {
|
for _, t := range objectTagData.Tags {
|
||||||
// t.SlugName = strings.ToLower(t.SlugName)
|
t.SlugName = strings.ToLower(t.SlugName)
|
||||||
thisObjTagNameList = append(thisObjTagNameList, t.SlugName)
|
thisObjTagNameList = append(thisObjTagNameList, t.SlugName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
@ -19,6 +20,7 @@ import (
|
||||||
"github.com/answerdev/answer/pkg/uid"
|
"github.com/answerdev/answer/pkg/uid"
|
||||||
"github.com/disintegration/imaging"
|
"github.com/disintegration/imaging"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
exifremove "github.com/scottleedavis/go-exif-remove"
|
||||||
"github.com/segmentfault/pacman/errors"
|
"github.com/segmentfault/pacman/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -192,6 +194,7 @@ func (us *UploaderService) uploadFile(ctx *gin.Context, file *multipart.FileHead
|
||||||
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
|
return "", errors.InternalServer(reason.UnknownError).WithError(err).WithStack()
|
||||||
}
|
}
|
||||||
defer src.Close()
|
defer src.Close()
|
||||||
|
Dexif(filePath, filePath)
|
||||||
|
|
||||||
if !checker.IsSupportedImageFile(src, filepath.Ext(fileSubPath)) {
|
if !checker.IsSupportedImageFile(src, filepath.Ext(fileSubPath)) {
|
||||||
return "", errors.BadRequest(reason.UploadFileUnsupportedFileFormat)
|
return "", errors.BadRequest(reason.UploadFileUnsupportedFileFormat)
|
||||||
|
@ -200,3 +203,19 @@ func (us *UploaderService) uploadFile(ctx *gin.Context, file *multipart.FileHead
|
||||||
url = fmt.Sprintf("%s/uploads/%s", siteGeneral.SiteUrl, fileSubPath)
|
url = fmt.Sprintf("%s/uploads/%s", siteGeneral.SiteUrl, fileSubPath)
|
||||||
return url, nil
|
return url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Dexif(filepath string, destpath string) error {
|
||||||
|
img, err := ioutil.ReadFile(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
noExifBytes, err := exifremove.Remove(img)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.WriteFile(destpath, noExifBytes, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ func (us *UserAdminService) UpdateUserRole(ctx context.Context, req *schema.Upda
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
us.authService.RemoveAllUserTokens(ctx, req.UserID)
|
us.authService.RemoveUserTokens(ctx, req.UserID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ func (us *UserAdminService) UpdateUserPassword(ctx context.Context, req *schema.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// logout this user
|
// logout this user
|
||||||
us.authService.RemoveAllUserTokens(ctx, req.UserID)
|
us.authService.RemoveUserTokens(ctx, req.UserID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -535,37 +535,66 @@ func (us *UserService) UserChangeEmailSendCode(ctx context.Context, req *schema.
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserChangeEmailVerify user change email verify code
|
// UserChangeEmailVerify user change email verify code
|
||||||
func (us *UserService) UserChangeEmailVerify(ctx context.Context, content string) (err error) {
|
func (us *UserService) UserChangeEmailVerify(ctx context.Context, content string) (resp *schema.GetUserResp, err error) {
|
||||||
data := &schema.EmailCodeContent{}
|
data := &schema.EmailCodeContent{}
|
||||||
err = data.FromJSONString(content)
|
err = data.FromJSONString(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.BadRequest(reason.EmailVerifyURLExpired)
|
return nil, errors.BadRequest(reason.EmailVerifyURLExpired)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, exist, err := us.userRepo.GetByEmail(ctx, data.Email)
|
_, exist, err := us.userRepo.GetByEmail(ctx, data.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if exist {
|
if exist {
|
||||||
return errors.BadRequest(reason.EmailDuplicate)
|
return nil, errors.BadRequest(reason.EmailDuplicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, exist, err = us.userRepo.GetByUserID(ctx, data.UserID)
|
userInfo, exist, err := us.userRepo.GetByUserID(ctx, data.UserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !exist {
|
if !exist {
|
||||||
return errors.BadRequest(reason.UserNotFound)
|
return nil, errors.BadRequest(reason.UserNotFound)
|
||||||
}
|
}
|
||||||
err = us.userRepo.UpdateEmail(ctx, data.UserID, data.Email)
|
err = us.userRepo.UpdateEmail(ctx, data.UserID, data.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.BadRequest(reason.UserNotFound)
|
return nil, errors.BadRequest(reason.UserNotFound)
|
||||||
}
|
}
|
||||||
err = us.userRepo.UpdateEmailStatus(ctx, data.UserID, entity.EmailStatusAvailable)
|
err = us.userRepo.UpdateEmailStatus(ctx, data.UserID, entity.EmailStatusAvailable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
roleID, err := us.userRoleService.GetUserRole(ctx, userInfo.ID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = &schema.GetUserResp{}
|
||||||
|
resp.GetFromUserEntity(userInfo)
|
||||||
|
userCacheInfo := &entity.UserCacheInfo{
|
||||||
|
UserID: userInfo.ID,
|
||||||
|
EmailStatus: entity.EmailStatusAvailable,
|
||||||
|
UserStatus: userInfo.Status,
|
||||||
|
RoleID: roleID,
|
||||||
|
}
|
||||||
|
resp.AccessToken, err = us.authService.SetUserCacheInfo(ctx, userCacheInfo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// User verified email will update user email status. So user status cache should be updated.
|
||||||
|
if err = us.authService.SetUserStatus(ctx, userCacheInfo); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp.RoleID = userCacheInfo.RoleID
|
||||||
|
if resp.RoleID == role.RoleAdminID {
|
||||||
|
err = us.authService.SetAdminUserCacheInfo(ctx, resp.AccessToken, &entity.UserCacheInfo{UserID: userInfo.ID})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getSiteUrl get site url
|
// getSiteUrl get site url
|
||||||
|
|
|
@ -34,6 +34,10 @@ func Markdown2HTML(source string) string {
|
||||||
}
|
}
|
||||||
html := buf.String()
|
html := buf.String()
|
||||||
filter := bluemonday.UGCPolicy()
|
filter := bluemonday.UGCPolicy()
|
||||||
|
filter.AllowStyling()
|
||||||
|
filter.RequireNoFollowOnLinks(false)
|
||||||
|
filter.RequireParseableURLs(false)
|
||||||
|
filter.RequireNoFollowOnFullyQualifiedLinks(false)
|
||||||
html = filter.Sanitize(html)
|
html = filter.Sanitize(html)
|
||||||
return html
|
return html
|
||||||
}
|
}
|
||||||
|
@ -110,6 +114,7 @@ func (r *DangerousHTMLRenderer) renderLink(w util.BufWriter, source []byte, node
|
||||||
n := node.(*ast.Link)
|
n := node.(*ast.Link)
|
||||||
if entering && r.renderLinkIsUrl(string(n.Destination)) {
|
if entering && r.renderLinkIsUrl(string(n.Destination)) {
|
||||||
_, _ = w.WriteString("<a href=\"")
|
_, _ = w.WriteString("<a href=\"")
|
||||||
|
// _, _ = w.WriteString("<a test=\"1\" rel=\"nofollow\" href=\"")
|
||||||
if r.Unsafe || !html.IsDangerousURL(n.Destination) {
|
if r.Unsafe || !html.IsDangerousURL(n.Destination) {
|
||||||
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,5 @@ func TestUrlTitle(t *testing.T) {
|
||||||
for _, title := range list {
|
for _, title := range list {
|
||||||
formatTitle := UrlTitle(title)
|
formatTitle := UrlTitle(title)
|
||||||
spew.Dump(formatTitle)
|
spew.Dump(formatTitle)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ func EnShortID(id string) string {
|
||||||
if ShortIDSwitch {
|
if ShortIDSwitch {
|
||||||
num, err := strconv.ParseInt(id, 10, 64)
|
num, err := strconv.ParseInt(id, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return id
|
||||||
}
|
}
|
||||||
return NumToShortID(num)
|
return NumToShortID(num)
|
||||||
}
|
}
|
||||||
|
|
|
@ -336,6 +336,7 @@ export interface SiteSettings {
|
||||||
theme: AdminSettingsTheme;
|
theme: AdminSettingsTheme;
|
||||||
site_seo: AdminSettingsSeo;
|
site_seo: AdminSettingsSeo;
|
||||||
version: string;
|
version: string;
|
||||||
|
revision: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AdminSettingBranding {
|
export interface AdminSettingBranding {
|
||||||
|
|
|
@ -11,6 +11,7 @@ const Index: FC = () => {
|
||||||
(state) => state.items,
|
(state) => state.items,
|
||||||
);
|
);
|
||||||
const appVersion = siteInfoStore((_) => _.version);
|
const appVersion = siteInfoStore((_) => _.version);
|
||||||
|
const hashVersion = siteInfoStore((_) => _.revision);
|
||||||
const setAppGenerator = () => {
|
const setAppGenerator = () => {
|
||||||
if (!appVersion) {
|
if (!appVersion) {
|
||||||
return;
|
return;
|
||||||
|
@ -19,7 +20,7 @@ const Index: FC = () => {
|
||||||
if (generatorMetaNode) {
|
if (generatorMetaNode) {
|
||||||
generatorMetaNode.setAttribute(
|
generatorMetaNode.setAttribute(
|
||||||
'content',
|
'content',
|
||||||
`Answer ${appVersion} - https://github.com/answerdev/answer`,
|
`Answer ${appVersion} - https://github.com/answerdev/answer version ${hashVersion}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,8 +6,9 @@ import { DEFAULT_SITE_NAME } from '@/common/constants';
|
||||||
interface SiteInfoType {
|
interface SiteInfoType {
|
||||||
siteInfo: AdminSettingsGeneral;
|
siteInfo: AdminSettingsGeneral;
|
||||||
version: string;
|
version: string;
|
||||||
|
revision: string;
|
||||||
update: (params: AdminSettingsGeneral) => void;
|
update: (params: AdminSettingsGeneral) => void;
|
||||||
updateVersion: (ver: string) => void;
|
updateVersion: (ver: string, revision: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const siteInfo = create<SiteInfoType>((set) => ({
|
const siteInfo = create<SiteInfoType>((set) => ({
|
||||||
|
@ -20,6 +21,7 @@ const siteInfo = create<SiteInfoType>((set) => ({
|
||||||
permalink: 1,
|
permalink: 1,
|
||||||
},
|
},
|
||||||
version: '',
|
version: '',
|
||||||
|
revision: '',
|
||||||
update: (params) =>
|
update: (params) =>
|
||||||
set((_) => {
|
set((_) => {
|
||||||
const o = { ..._.siteInfo, ...params };
|
const o = { ..._.siteInfo, ...params };
|
||||||
|
@ -30,9 +32,9 @@ const siteInfo = create<SiteInfoType>((set) => ({
|
||||||
siteInfo: o,
|
siteInfo: o,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
updateVersion: (ver) => {
|
updateVersion: (ver, revision) => {
|
||||||
set(() => {
|
set(() => {
|
||||||
return { version: ver };
|
return { version: ver, revision };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -305,7 +305,9 @@ export const initAppSettingsStore = async () => {
|
||||||
const appSettings = await getAppSettings();
|
const appSettings = await getAppSettings();
|
||||||
if (appSettings) {
|
if (appSettings) {
|
||||||
siteInfoStore.getState().update(appSettings.general);
|
siteInfoStore.getState().update(appSettings.general);
|
||||||
siteInfoStore.getState().updateVersion(appSettings.version);
|
siteInfoStore
|
||||||
|
.getState()
|
||||||
|
.updateVersion(appSettings.version, appSettings.revision);
|
||||||
interfaceStore.getState().update(appSettings.interface);
|
interfaceStore.getState().update(appSettings.interface);
|
||||||
brandingStore.getState().update(appSettings.branding);
|
brandingStore.getState().update(appSettings.branding);
|
||||||
loginSettingStore.getState().update(appSettings.login);
|
loginSettingStore.getState().update(appSettings.login);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="border-bottom py-2 comment-item border-top">
|
<div class="border-bottom py-2 comment-item border-top">
|
||||||
<div class="d-block">
|
<div class="d-block">
|
||||||
<div class="fmt fs-14">
|
<div class="fmt fs-14">
|
||||||
{{templateHTML .ParsedText}}
|
{{formatLinkNofollow .ParsedText}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-between fs-14">
|
<div class="d-flex justify-content-between fs-14">
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||||
<title>{{.title}}</title>
|
<title>{{.title}}</title>
|
||||||
<meta name="description" content="{{.description}}" data-rh="true" />
|
<meta name="description" content="{{.description}}" data-rh="true" />
|
||||||
<meta name="generator" content="Answer {{.Version}} - https://github.com/answerdev/answer">
|
<meta name="generator" content="Answer {{.Version}} - https://github.com/answerdev/answer version {{.Revision}}">
|
||||||
{{if .keywords }}<meta name="keywords" content="{{.keywords}}" data-rh="true" />{{end}}
|
{{if .keywords }}<meta name="keywords" content="{{.keywords}}" data-rh="true" />{{end}}
|
||||||
|
|
||||||
<link rel="canonical" href="{{.siteinfo.Canonical}}" />
|
<link rel="canonical" href="{{.siteinfo.Canonical}}" />
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<article class="fmt text-break text-wrap mt-4">
|
<article class="fmt text-break text-wrap mt-4">
|
||||||
{{templateHTML .detail.HTML}}
|
{{formatLinkNofollow .detail.HTML}}
|
||||||
</article>
|
</article>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div role="group" class="btn-group">
|
<div role="group" class="btn-group">
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
{{range .answers}}
|
{{range .answers}}
|
||||||
<div id="10020000000000930" class="answer-item py-4">
|
<div id="10020000000000930" class="answer-item py-4">
|
||||||
<article class="fmt">
|
<article class="fmt">
|
||||||
{{templateHTML .HTML}}
|
{{formatLinkNofollow .HTML}}
|
||||||
</article>
|
</article>
|
||||||
<div class="d-flex align-items-center mt-4">
|
<div class="d-flex align-items-center mt-4">
|
||||||
<div class="">
|
<div class="">
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
>{{$.tag.SlugName}}</a
|
>{{$.tag.SlugName}}</a
|
||||||
>
|
>
|
||||||
</h3>
|
</h3>
|
||||||
<p class="text-break">{{templateHTML $.tag.ParsedText}}</p>
|
<p class="text-break">{{formatLinkNofollow $.tag.ParsedText}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="mb-3 d-flex flex-wrap justify-content-between">
|
<div class="mb-3 d-flex flex-wrap justify-content-between">
|
||||||
|
|
Loading…
Reference in New Issue