This commit is contained in:
@@ -5,11 +5,13 @@ const { requireAuth } = require("../middleware/auth");
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
const HEX_COLOR_RE = /^#[0-9a-fA-F]{6}$/;
|
||||||
|
|
||||||
// POST /api/hibolia/orders — public order submission
|
// POST /api/hibolia/orders — public order submission
|
||||||
router.post("/orders", async (req, res) => {
|
router.post("/orders", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const { name, surname, email, message, color, shipping } = req.body || {};
|
const { name, surname, email, message, color, customColor, shipping } =
|
||||||
|
req.body || {};
|
||||||
if (!name || !surname || !email || !message || !color || !shipping) {
|
if (!name || !surname || !email || !message || !color || !shipping) {
|
||||||
return res
|
return res
|
||||||
.status(400)
|
.status(400)
|
||||||
@@ -18,6 +20,9 @@ router.post("/orders", async (req, res) => {
|
|||||||
if (!HiboliaOrder.COLORS.includes(color)) {
|
if (!HiboliaOrder.COLORS.includes(color)) {
|
||||||
return res.status(400).json({ error: "invalid color" });
|
return res.status(400).json({ error: "invalid color" });
|
||||||
}
|
}
|
||||||
|
if (color === "custom" && !HEX_COLOR_RE.test(String(customColor || ""))) {
|
||||||
|
return res.status(400).json({ error: "invalid custom color" });
|
||||||
|
}
|
||||||
if (!EMAIL_RE.test(String(email))) {
|
if (!EMAIL_RE.test(String(email))) {
|
||||||
return res.status(400).json({ error: "invalid email" });
|
return res.status(400).json({ error: "invalid email" });
|
||||||
}
|
}
|
||||||
@@ -27,6 +32,7 @@ router.post("/orders", async (req, res) => {
|
|||||||
email,
|
email,
|
||||||
message,
|
message,
|
||||||
color,
|
color,
|
||||||
|
customColor: color === "custom" ? String(customColor).toLowerCase() : undefined,
|
||||||
shipping,
|
shipping,
|
||||||
});
|
});
|
||||||
res.status(201).json({ id: order._id });
|
res.status(201).json({ id: order._id });
|
||||||
|
|||||||
@@ -12,9 +12,19 @@ const COLORS = [
|
|||||||
"black",
|
"black",
|
||||||
"white",
|
"white",
|
||||||
"pink",
|
"pink",
|
||||||
|
"turquoise",
|
||||||
|
"teal",
|
||||||
|
"navy",
|
||||||
|
"lavender",
|
||||||
|
"magenta",
|
||||||
|
"lime",
|
||||||
|
"coral",
|
||||||
|
"custom",
|
||||||
"none",
|
"none",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const HEX_COLOR_RE = /^#[0-9a-f]{6}$/;
|
||||||
|
|
||||||
const hiboliaOrderSchema = new mongoose.Schema(
|
const hiboliaOrderSchema = new mongoose.Schema(
|
||||||
{
|
{
|
||||||
name: { type: String, required: true, trim: true, maxlength: 100 },
|
name: { type: String, required: true, trim: true, maxlength: 100 },
|
||||||
@@ -22,6 +32,18 @@ const hiboliaOrderSchema = new mongoose.Schema(
|
|||||||
email: { type: String, required: true, trim: true, lowercase: true },
|
email: { type: String, required: true, trim: true, lowercase: true },
|
||||||
message: { type: String, required: true, trim: true, maxlength: 2000 },
|
message: { type: String, required: true, trim: true, maxlength: 2000 },
|
||||||
color: { type: String, required: true, enum: COLORS },
|
color: { type: String, required: true, enum: COLORS },
|
||||||
|
customColor: {
|
||||||
|
type: String,
|
||||||
|
trim: true,
|
||||||
|
lowercase: true,
|
||||||
|
required: [
|
||||||
|
function () {
|
||||||
|
return this.color === "custom";
|
||||||
|
},
|
||||||
|
"customColor is required when color is custom",
|
||||||
|
],
|
||||||
|
match: [HEX_COLOR_RE, "invalid custom color"],
|
||||||
|
},
|
||||||
shipping: { type: String, required: true, trim: true, maxlength: 2000 },
|
shipping: { type: String, required: true, trim: true, maxlength: 2000 },
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
|
|||||||
@@ -22,9 +22,22 @@ const COLOR_HEX: Record<string, string> = {
|
|||||||
yellow: '#e2cf3c',
|
yellow: '#e2cf3c',
|
||||||
green: '#5fae4e',
|
green: '#5fae4e',
|
||||||
blue: '#4c8be0',
|
blue: '#4c8be0',
|
||||||
purple: '#9b59d0'
|
purple: '#9b59d0',
|
||||||
|
black: '#1a1a1a',
|
||||||
|
white: '#f2f2f2',
|
||||||
|
pink: '#e88fb3',
|
||||||
|
turquoise: '#40c4b8',
|
||||||
|
teal: '#17857c',
|
||||||
|
navy: '#34549c',
|
||||||
|
lavender: '#b98fe0',
|
||||||
|
magenta: '#cf479f',
|
||||||
|
lime: '#a8d14e',
|
||||||
|
coral: '#ef8368'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const orderSwatch = (order: any) =>
|
||||||
|
order.color === 'custom' ? order.customColor : COLOR_HEX[order.color] || 'transparent';
|
||||||
|
|
||||||
const formatUptime = (seconds: number) => {
|
const formatUptime = (seconds: number) => {
|
||||||
const h = Math.floor(seconds / 3600);
|
const h = Math.floor(seconds / 3600);
|
||||||
const m = Math.floor((seconds % 3600) / 60);
|
const m = Math.floor((seconds % 3600) / 60);
|
||||||
@@ -153,8 +166,8 @@ const onLogout = () => redirectToLogin();
|
|||||||
<td class="msg-cell">{{ order.message }}</td>
|
<td class="msg-cell">{{ order.message }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="color-chip">
|
<span class="color-chip">
|
||||||
<span class="swatch" :style="{ background: COLOR_HEX[order.color] || 'transparent' }" aria-hidden="true"></span>
|
<span class="swatch" :style="{ background: orderSwatch(order) }" aria-hidden="true"></span>
|
||||||
{{ $t(`order.hibolia.colors.${order.color}`) }}
|
{{ $t(`order.hibolia.colors.${order.color}`) }}<template v-if="order.color === 'custom'"> {{ order.customColor }}</template>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="msg-cell">{{ order.shipping }}</td>
|
<td class="msg-cell">{{ order.shipping }}</td>
|
||||||
|
|||||||
@@ -23,23 +23,37 @@ const COLOR_OPTIONS = [
|
|||||||
{ value: 'black', hex: '#1a1a1a' },
|
{ value: 'black', hex: '#1a1a1a' },
|
||||||
{ value: 'white', hex: '#f2f2f2' },
|
{ value: 'white', hex: '#f2f2f2' },
|
||||||
{ value: 'pink', hex: '#e88fb3' },
|
{ value: 'pink', hex: '#e88fb3' },
|
||||||
|
{ value: 'turquoise', hex: '#40c4b8' },
|
||||||
|
{ value: 'teal', hex: '#17857c' },
|
||||||
|
{ value: 'navy', hex: '#34549c' },
|
||||||
|
{ value: 'lavender', hex: '#b98fe0' },
|
||||||
|
{ value: 'magenta', hex: '#cf479f' },
|
||||||
|
{ value: 'lime', hex: '#a8d14e' },
|
||||||
|
{ value: 'coral', hex: '#ef8368' },
|
||||||
|
{ value: 'custom', hex: '#40c4b8' },
|
||||||
{ value: 'none', hex: '#9e9e9e' }
|
{ value: 'none', hex: '#9e9e9e' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const DEFAULT_CUSTOM_COLOR = '#40c4b8';
|
||||||
|
const HEX_COLOR_RE = /^#[0-9a-fA-F]{6}$/;
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
name: '',
|
name: '',
|
||||||
surname: '',
|
surname: '',
|
||||||
email: '',
|
email: '',
|
||||||
message: '',
|
message: '',
|
||||||
color: '',
|
color: 'none',
|
||||||
|
customColor: DEFAULT_CUSTOM_COLOR,
|
||||||
shipping: ''
|
shipping: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const DEFAULT_EDGE_COLOR = '#d8d2c6';
|
const DEFAULT_EDGE_COLOR = '#d8d2c6';
|
||||||
|
|
||||||
const selectedColorHex = computed(
|
const selectedColorHex = computed(() => {
|
||||||
() => COLOR_OPTIONS.find((o) => o.value === form.color)?.hex ?? DEFAULT_EDGE_COLOR
|
if (form.color === 'custom') return form.customColor;
|
||||||
);
|
if (form.color === 'none') return DEFAULT_EDGE_COLOR;
|
||||||
|
return COLOR_OPTIONS.find((o) => o.value === form.color)?.hex ?? DEFAULT_EDGE_COLOR;
|
||||||
|
});
|
||||||
|
|
||||||
const submitting = ref(false);
|
const submitting = ref(false);
|
||||||
const errorMsg = ref('');
|
const errorMsg = ref('');
|
||||||
@@ -62,6 +76,11 @@ const onSubmit = async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (form.color === 'custom' && !HEX_COLOR_RE.test(form.customColor)) {
|
||||||
|
errorMsg.value = $t('order.hibolia.error_invalid_color');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
await post('/hibolia/orders', {
|
await post('/hibolia/orders', {
|
||||||
@@ -70,13 +89,16 @@ const onSubmit = async () => {
|
|||||||
email: form.email.trim(),
|
email: form.email.trim(),
|
||||||
message: form.message.trim(),
|
message: form.message.trim(),
|
||||||
color: form.color,
|
color: form.color,
|
||||||
|
customColor:
|
||||||
|
form.color === 'custom' ? form.customColor.toLowerCase() : undefined,
|
||||||
shipping: form.shipping.trim()
|
shipping: form.shipping.trim()
|
||||||
});
|
});
|
||||||
form.name = '';
|
form.name = '';
|
||||||
form.surname = '';
|
form.surname = '';
|
||||||
form.email = '';
|
form.email = '';
|
||||||
form.message = '';
|
form.message = '';
|
||||||
form.color = '';
|
form.color = 'none';
|
||||||
|
form.customColor = DEFAULT_CUSTOM_COLOR;
|
||||||
form.shipping = '';
|
form.shipping = '';
|
||||||
await navigateTo(localePath('/projects/hibolia/thanks'));
|
await navigateTo(localePath('/projects/hibolia/thanks'));
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
@@ -185,10 +207,28 @@ const onSubmit = async () => {
|
|||||||
:disabled="submitting"
|
:disabled="submitting"
|
||||||
:id="`order-color-${option.value}`"
|
:id="`order-color-${option.value}`"
|
||||||
/>
|
/>
|
||||||
<span class="swatch" :style="{ background: option.hex }" aria-hidden="true"></span>
|
<span
|
||||||
|
class="swatch"
|
||||||
|
:style="{ background: option.value === 'custom' ? form.customColor : option.hex }"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
<span class="color-name">{{ $t(`order.hibolia.colors.${option.value}`) }}</span>
|
<span class="color-name">{{ $t(`order.hibolia.colors.${option.value}`) }}</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="form.color === 'custom'" class="custom-color-row">
|
||||||
|
<label for="order-custom-color">{{ $t('order.hibolia.custom_color_label') }}:</label>
|
||||||
|
<input
|
||||||
|
id="order-custom-color"
|
||||||
|
v-model="form.customColor"
|
||||||
|
type="color"
|
||||||
|
name="customColor"
|
||||||
|
:disabled="submitting"
|
||||||
|
/>
|
||||||
|
<span class="custom-color-hex">{{ form.customColor }}</span>
|
||||||
|
</div>
|
||||||
|
<p v-if="form.color === 'custom'" class="custom-color-note">
|
||||||
|
{{ $t('order.hibolia.custom_color_note') }}
|
||||||
|
</p>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<p>{{ $t('order.hibolia.preview_note') }}</p>
|
<p>{{ $t('order.hibolia.preview_note') }}</p>
|
||||||
@@ -383,6 +423,49 @@ const onSubmit = async () => {
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-color-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-family: 'Hurmit', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--color-link);
|
||||||
|
min-width: 0;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='color'] {
|
||||||
|
width: 48px;
|
||||||
|
height: 30px;
|
||||||
|
padding: 2px;
|
||||||
|
background: var(--color-background);
|
||||||
|
border: 1px solid var(--color-border-color);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
outline: 1px dashed var(--color-link);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-color-hex {
|
||||||
|
font-family: 'Hurmit', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-color-note {
|
||||||
|
font-family: 'Hurmit', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--color-text);
|
||||||
|
opacity: 0.75;
|
||||||
|
margin: 8px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
.deck-preview {
|
.deck-preview {
|
||||||
height: 300px;
|
height: 300px;
|
||||||
margin: 0 0 14px;
|
margin: 0 0 14px;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
"email_label": "correu",
|
"email_label": "correu",
|
||||||
"message_label": "missatge",
|
"message_label": "missatge",
|
||||||
"color_label": "color",
|
"color_label": "color",
|
||||||
|
"custom_color_label": "color personalitzat",
|
||||||
|
"custom_color_note": "El pintaré amb el color que més s'assembli al que has seleccionat",
|
||||||
"shipping_label": "enviament",
|
"shipping_label": "enviament",
|
||||||
"colors": {
|
"colors": {
|
||||||
"red": "Vermell",
|
"red": "Vermell",
|
||||||
@@ -82,6 +84,14 @@
|
|||||||
"black": "Negre",
|
"black": "Negre",
|
||||||
"white": "Blanc",
|
"white": "Blanc",
|
||||||
"pink": "Rosa",
|
"pink": "Rosa",
|
||||||
|
"turquoise": "Turquesa",
|
||||||
|
"teal": "Verd blavós",
|
||||||
|
"navy": "Blau marí",
|
||||||
|
"lavender": "Llavanda",
|
||||||
|
"magenta": "Magenta",
|
||||||
|
"lime": "Verd llima",
|
||||||
|
"coral": "Coral",
|
||||||
|
"custom": "Personalitzat",
|
||||||
"none": "Cap"
|
"none": "Cap"
|
||||||
},
|
},
|
||||||
"submit": "enviar comanda",
|
"submit": "enviar comanda",
|
||||||
@@ -89,6 +99,7 @@
|
|||||||
"success": "Comanda enviada correctament.",
|
"success": "Comanda enviada correctament.",
|
||||||
"error_required": "Tots els camps són obligatoris.",
|
"error_required": "Tots els camps són obligatoris.",
|
||||||
"error_invalid": "Algunes dades no són vàlides. Revisa el formulari i torna-ho a provar.",
|
"error_invalid": "Algunes dades no són vàlides. Revisa el formulari i torna-ho a provar.",
|
||||||
|
"error_invalid_color": "El color personalitzat no és vàlid.",
|
||||||
"error_generic": "No s'ha pogut enviar la comanda. Torna-ho a provar més tard.",
|
"error_generic": "No s'ha pogut enviar la comanda. Torna-ho a provar més tard.",
|
||||||
"form_title": "Formulari de comanda de baralla de cartes",
|
"form_title": "Formulari de comanda de baralla de cartes",
|
||||||
"intro": "Aquest formulari servirà per registrar oficialment la teva comanda de baralla de cartes.",
|
"intro": "Aquest formulari servirà per registrar oficialment la teva comanda de baralla de cartes.",
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
"email_label": "email",
|
"email_label": "email",
|
||||||
"message_label": "message",
|
"message_label": "message",
|
||||||
"color_label": "color",
|
"color_label": "color",
|
||||||
|
"custom_color_label": "custom color",
|
||||||
|
"custom_color_note": "I will paint it with the color that most closely resembles the one you selected",
|
||||||
"shipping_label": "shipping",
|
"shipping_label": "shipping",
|
||||||
"colors": {
|
"colors": {
|
||||||
"red": "Red",
|
"red": "Red",
|
||||||
@@ -82,6 +84,14 @@
|
|||||||
"black": "Black",
|
"black": "Black",
|
||||||
"white": "White",
|
"white": "White",
|
||||||
"pink": "Pink",
|
"pink": "Pink",
|
||||||
|
"turquoise": "Turquoise",
|
||||||
|
"teal": "Teal",
|
||||||
|
"navy": "Navy",
|
||||||
|
"lavender": "Lavender",
|
||||||
|
"magenta": "Magenta",
|
||||||
|
"lime": "Lime",
|
||||||
|
"coral": "Coral",
|
||||||
|
"custom": "Custom",
|
||||||
"none": "None"
|
"none": "None"
|
||||||
},
|
},
|
||||||
"submit": "send order",
|
"submit": "send order",
|
||||||
@@ -89,6 +99,7 @@
|
|||||||
"success": "Order sent successfully.",
|
"success": "Order sent successfully.",
|
||||||
"error_required": "All fields are required.",
|
"error_required": "All fields are required.",
|
||||||
"error_invalid": "Some data is invalid. Check the form and try again.",
|
"error_invalid": "Some data is invalid. Check the form and try again.",
|
||||||
|
"error_invalid_color": "The custom color is not valid.",
|
||||||
"error_generic": "Could not send the order. Try again later.",
|
"error_generic": "Could not send the order. Try again later.",
|
||||||
"form_title": "Playing card deck order form",
|
"form_title": "Playing card deck order form",
|
||||||
"intro": "This form will be used to officially register your playing card deck order.",
|
"intro": "This form will be used to officially register your playing card deck order.",
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
"email_label": "email",
|
"email_label": "email",
|
||||||
"message_label": "mensaje",
|
"message_label": "mensaje",
|
||||||
"color_label": "color",
|
"color_label": "color",
|
||||||
|
"custom_color_label": "color personalizado",
|
||||||
|
"custom_color_note": "Lo pintaré con el color que más se parezca al que has seleccionado",
|
||||||
"shipping_label": "envío",
|
"shipping_label": "envío",
|
||||||
"colors": {
|
"colors": {
|
||||||
"red": "Rojo",
|
"red": "Rojo",
|
||||||
@@ -82,6 +84,14 @@
|
|||||||
"black": "Negro",
|
"black": "Negro",
|
||||||
"white": "Blanco",
|
"white": "Blanco",
|
||||||
"pink": "Rosa",
|
"pink": "Rosa",
|
||||||
|
"turquoise": "Turquesa",
|
||||||
|
"teal": "Verde azulado",
|
||||||
|
"navy": "Azul marino",
|
||||||
|
"lavender": "Lavanda",
|
||||||
|
"magenta": "Magenta",
|
||||||
|
"lime": "Verde lima",
|
||||||
|
"coral": "Coral",
|
||||||
|
"custom": "Personalizado",
|
||||||
"none": "Ninguno"
|
"none": "Ninguno"
|
||||||
},
|
},
|
||||||
"submit": "enviar pedido",
|
"submit": "enviar pedido",
|
||||||
@@ -89,6 +99,7 @@
|
|||||||
"success": "Pedido enviado correctamente.",
|
"success": "Pedido enviado correctamente.",
|
||||||
"error_required": "Todos los campos son obligatorios.",
|
"error_required": "Todos los campos son obligatorios.",
|
||||||
"error_invalid": "Algunos datos no son válidos. Revisa el formulario e inténtalo de nuevo.",
|
"error_invalid": "Algunos datos no son válidos. Revisa el formulario e inténtalo de nuevo.",
|
||||||
|
"error_invalid_color": "El color personalizado no es válido.",
|
||||||
"error_generic": "No se pudo enviar el pedido. Inténtalo más tarde.",
|
"error_generic": "No se pudo enviar el pedido. Inténtalo más tarde.",
|
||||||
"form_title": "Formulario de orden de baraja de cartas",
|
"form_title": "Formulario de orden de baraja de cartas",
|
||||||
"intro": "Este formulario será para registrar oficialmente tu pedido de baraja de cartas.",
|
"intro": "Este formulario será para registrar oficialmente tu pedido de baraja de cartas.",
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
"email_label": "邮箱",
|
"email_label": "邮箱",
|
||||||
"message_label": "留言",
|
"message_label": "留言",
|
||||||
"color_label": "颜色",
|
"color_label": "颜色",
|
||||||
|
"custom_color_label": "自定义颜色",
|
||||||
|
"custom_color_note": "我会用与您所选颜色最接近的颜色来绘制",
|
||||||
"shipping_label": "配送",
|
"shipping_label": "配送",
|
||||||
"colors": {
|
"colors": {
|
||||||
"red": "红色",
|
"red": "红色",
|
||||||
@@ -82,6 +84,14 @@
|
|||||||
"black": "黑色",
|
"black": "黑色",
|
||||||
"white": "白色",
|
"white": "白色",
|
||||||
"pink": "粉色",
|
"pink": "粉色",
|
||||||
|
"turquoise": "青绿色",
|
||||||
|
"teal": "蓝绿色",
|
||||||
|
"navy": "藏青色",
|
||||||
|
"lavender": "淡紫色",
|
||||||
|
"magenta": "洋红色",
|
||||||
|
"lime": "黄绿色",
|
||||||
|
"coral": "珊瑚色",
|
||||||
|
"custom": "自定义",
|
||||||
"none": "无"
|
"none": "无"
|
||||||
},
|
},
|
||||||
"submit": "提交订单",
|
"submit": "提交订单",
|
||||||
@@ -89,6 +99,7 @@
|
|||||||
"success": "订单提交成功。",
|
"success": "订单提交成功。",
|
||||||
"error_required": "所有字段均为必填。",
|
"error_required": "所有字段均为必填。",
|
||||||
"error_invalid": "部分数据无效,请检查表单后重试。",
|
"error_invalid": "部分数据无效,请检查表单后重试。",
|
||||||
|
"error_invalid_color": "自定义颜色无效。",
|
||||||
"error_generic": "无法提交订单,请稍后再试。",
|
"error_generic": "无法提交订单,请稍后再试。",
|
||||||
"form_title": "纸牌订购表单",
|
"form_title": "纸牌订购表单",
|
||||||
"intro": "此表单用于正式登记您的纸牌订单。",
|
"intro": "此表单用于正式登记您的纸牌订单。",
|
||||||
|
|||||||
Reference in New Issue
Block a user