mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-24 08:20:31 +08:00
Add product detail page.
This commit is contained in:
parent
39ab71c5db
commit
e19f07c521
@ -28,6 +28,7 @@ type Product struct {
|
||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||
|
||||
Image string `xorm:"varchar(100)" json:"image"`
|
||||
Detail string `xorm:"varchar(100)" json:"detail"`
|
||||
Tag string `xorm:"varchar(100)" json:"tag"`
|
||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||
Price int `json:"price"`
|
||||
|
@ -45,6 +45,7 @@ import CertListPage from "./CertListPage";
|
||||
import CertEditPage from "./CertEditPage";
|
||||
import ProductListPage from "./ProductListPage";
|
||||
import ProductEditPage from "./ProductEditPage";
|
||||
import ProductBuyPage from "./ProductBuyPage";
|
||||
import PaymentListPage from "./PaymentListPage";
|
||||
import PaymentEditPage from "./PaymentEditPage";
|
||||
import AccountPage from "./account/AccountPage";
|
||||
@ -503,6 +504,7 @@ class App extends Component {
|
||||
<Route exact path="/certs/:certName" render={(props) => this.renderLoginIfNotLoggedIn(<CertEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/products" render={(props) => this.renderLoginIfNotLoggedIn(<ProductListPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/products/:productName" render={(props) => this.renderLoginIfNotLoggedIn(<ProductEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/products/:productName/buy" render={(props) => this.renderLoginIfNotLoggedIn(<ProductBuyPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/payments" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentListPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/payments/:paymentName" render={(props) => this.renderLoginIfNotLoggedIn(<PaymentEditPage account={this.state.account} {...props} />)}/>
|
||||
<Route exact path="/records" render={(props) => this.renderLoginIfNotLoggedIn(<RecordListPage account={this.state.account} {...props} />)}/>
|
||||
|
@ -443,7 +443,6 @@ class ApplicationEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("application:Grant types"), i18next.t("application:Grant types - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
|
||||
<Select virtual={false} mode="tags" style={{width: '100%'}}
|
||||
value={this.state.application.grantTypes}
|
||||
onChange={(value => {
|
||||
@ -518,13 +517,13 @@ class ApplicationEditPage extends React.Component {
|
||||
if (!Setting.isMobile()) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Col span={11} style={{display:'flex',flexDirection:'column'}}>
|
||||
<a style={{marginBottom: '10px',display:'flex'}} target="_blank" rel="noreferrer" href={signUpUrl}>
|
||||
<Col span={11} style={{display:"flex", flexDirection: "column"}}>
|
||||
<a style={{marginBottom: "10px", display: "flex"}} target="_blank" rel="noreferrer" href={signUpUrl}>
|
||||
<Button type="primary">{i18next.t("application:Test signup page..")}</Button>
|
||||
</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888" ,alignItems:'center',overflow:'auto',flexDirection:'column',flex:'auto'}}>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems:"center", overflow:"auto", flexDirection:"column", flex: "auto"}}>
|
||||
{
|
||||
this.state.application.enablePassword ? (
|
||||
<SignupPage application={this.state.application} />
|
||||
@ -534,13 +533,13 @@ class ApplicationEditPage extends React.Component {
|
||||
}
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={11} style={{display:'flex',flexDirection:'column'}}>
|
||||
<a style={{marginBottom: '10px',display:'flex'}} target="_blank" rel="noreferrer" href={signInUrl}>
|
||||
<Col span={11} style={{display:"flex", flexDirection: "column"}}>
|
||||
<a style={{marginBottom: "10px", display: "flex"}} target="_blank" rel="noreferrer" href={signInUrl}>
|
||||
<Button type="primary">{i18next.t("application:Test signin page..")}</Button>
|
||||
</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888",alignItems:'center',overflow:'auto',flexDirection:'column',flex:'auto' }}>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems:"center", overflow:"auto", flexDirection:"column", flex: "auto"}}>
|
||||
<LoginPage type={"login"} mode={"signin"} application={this.state.application} />
|
||||
</div>
|
||||
</Col>
|
||||
@ -549,11 +548,11 @@ class ApplicationEditPage extends React.Component {
|
||||
} else{
|
||||
return(
|
||||
<React.Fragment>
|
||||
<Col span={24} style={{display:'flex',flexDirection:'column'}}>
|
||||
<a style={{marginBottom: '10px',display:'flex'}} target="_blank" rel="noreferrer" href={signUpUrl}>
|
||||
<Col span={24} style={{display:"flex", flexDirection: "column"}}>
|
||||
<a style={{marginBottom: "10px", display: "flex"}} target="_blank" rel="noreferrer" href={signUpUrl}>
|
||||
<Button type="primary">{i18next.t("application:Test signup page..")}</Button>
|
||||
</a>
|
||||
<div style={{marginBottom:'10px', width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888" ,alignItems:'center',overflow:'auto',flexDirection:'column',flex:'auto'}}>
|
||||
<div style={{marginBottom:"10px", width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
||||
{
|
||||
this.state.application.enablePassword ? (
|
||||
<SignupPage application={this.state.application} />
|
||||
@ -562,10 +561,10 @@ class ApplicationEditPage extends React.Component {
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<a style={{marginBottom: '10px',display:'flex'}} target="_blank" rel="noreferrer" href={signInUrl}>
|
||||
<a style={{marginBottom: "10px", display: "flex"}} target="_blank" rel="noreferrer" href={signInUrl}>
|
||||
<Button type="primary">{i18next.t("application:Test signin page..")}</Button>
|
||||
</a>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888",alignItems:'center',overflow:'auto',flexDirection:'column',flex:'auto' }}>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
||||
<LoginPage type={"login"} mode={"signin"} application={this.state.application} />
|
||||
</div>
|
||||
</Col>
|
||||
@ -579,13 +578,13 @@ class ApplicationEditPage extends React.Component {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Col span={(Setting.isMobile()) ? 24 : 11} style={{display:'flex',flexDirection:'column',flex:'auto'}} >
|
||||
<a style={{marginBottom: '10px'}} target="_blank" rel="noreferrer" href={promptUrl}>
|
||||
<Col span={(Setting.isMobile()) ? 24 : 11} style={{display:"flex", flexDirection: "column", flex: "auto"}} >
|
||||
<a style={{marginBottom: "10px"}} target="_blank" rel="noreferrer" href={promptUrl}>
|
||||
<Button type="primary">{i18next.t("application:Test prompt page..")}</Button>
|
||||
</a>
|
||||
<br style={(Setting.isMobile()) ? {display:'none'} : {}} />
|
||||
<br style={(Setting.isMobile()) ? {display:'none'} : {}} />
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888",flexDirection:'column',flex:'auto'}}>
|
||||
<br style={(Setting.isMobile()) ? {display: "none"} : {}} />
|
||||
<br style={(Setting.isMobile()) ? {display: "none"} : {}} />
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", flexDirection: "column", flex: "auto"}}>
|
||||
<PromptPage application={this.state.application} account={this.props.account} />
|
||||
</div>
|
||||
</Col>
|
||||
|
196
web/src/ProductBuyPage.js
Normal file
196
web/src/ProductBuyPage.js
Normal file
@ -0,0 +1,196 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Descriptions} from "antd";
|
||||
import i18next from "i18next";
|
||||
import * as ProductBackend from "./backend/ProductBackend";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Provider from "./auth/Provider";
|
||||
|
||||
class ProductBuyPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
productName: props.match?.params.productName,
|
||||
product: null,
|
||||
providers: [],
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getProduct();
|
||||
this.getPaymentProviders();
|
||||
}
|
||||
|
||||
getProduct() {
|
||||
ProductBackend.getProduct("admin", this.state.productName)
|
||||
.then((product) => {
|
||||
this.setState({
|
||||
product: product,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getPaymentProviders() {
|
||||
ProviderBackend.getProviders("admin")
|
||||
.then((res) => {
|
||||
this.setState({
|
||||
providers: res.filter(provider => provider.category === "Payment"),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getProductObj() {
|
||||
if (this.props.product !== undefined) {
|
||||
return this.props.product;
|
||||
} else {
|
||||
return this.state.product;
|
||||
}
|
||||
}
|
||||
|
||||
getCurrencySymbol(product) {
|
||||
if (product?.currency === "USD") {
|
||||
return "$";
|
||||
} else if (product?.currency === "CNY") {
|
||||
return "¥";
|
||||
} else {
|
||||
return "(Unknown currency)";
|
||||
}
|
||||
}
|
||||
|
||||
getCurrencyText(product) {
|
||||
if (product?.currency === "USD") {
|
||||
return i18next.t("product:USD");
|
||||
} else if (product?.currency === "CNY") {
|
||||
return i18next.t("product:CNY");
|
||||
} else {
|
||||
return "(Unknown currency)";
|
||||
}
|
||||
}
|
||||
|
||||
getProviders(product) {
|
||||
if (this.state.providers.length === 0 || product.providers.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let providerMap = {};
|
||||
this.state.providers.forEach(provider => {
|
||||
providerMap[provider.name] = provider;
|
||||
})
|
||||
|
||||
return product.providers.map(providerName => providerMap[providerName]);
|
||||
}
|
||||
|
||||
getPayUrl(product, provider) {
|
||||
if (product === null || provider === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `https://${provider.type}`;
|
||||
// if (provider.type === "WeChat") {
|
||||
// return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}`;
|
||||
// } else if (provider.type === "GitHub") {
|
||||
// return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}`;
|
||||
// }
|
||||
}
|
||||
|
||||
getPayButton(provider) {
|
||||
let text = provider.type;
|
||||
if (provider.type === "Alipay") {
|
||||
text = i18next.t("product:Alipay");
|
||||
} else if (provider.type === "WeChat Pay") {
|
||||
text = i18next.t("product:WeChat Pay");
|
||||
} else if (provider.type === "Paypal") {
|
||||
text = i18next.t("product:Paypal");
|
||||
}
|
||||
|
||||
return (
|
||||
<Button style={{height: "50px", borderWidth: "2px"}} shape="round" icon={
|
||||
<img style={{marginRight: "10px"}} width={36} height={36} src={Provider.getProviderLogo(provider)} alt={provider.displayName} />
|
||||
} size={"large"} >
|
||||
{
|
||||
text
|
||||
}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
renderProviderButton(provider, product) {
|
||||
return (
|
||||
<span key={provider.name} style={{width: "200px", marginRight: "20px", marginBottom: "10px"}}>
|
||||
<a style={{width: "200px"}} href={this.getPayUrl(product, provider)}>
|
||||
{
|
||||
this.getPayButton(provider)
|
||||
}
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
renderPay(product) {
|
||||
if (product === undefined || product === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (product.state !== "Published") {
|
||||
return i18next.t("product:This product is currently not in sale.");
|
||||
}
|
||||
if (product.providers.length === 0) {
|
||||
return i18next.t("product:There is no payment channel for this product.");
|
||||
}
|
||||
|
||||
const providers = this.getProviders(product);
|
||||
return providers.map(provider => {
|
||||
return this.renderProviderButton(provider, product);
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const product = this.getProductObj();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Descriptions title={i18next.t("product:Buy Product")} bordered>
|
||||
<Descriptions.Item label={i18next.t("general:Name")} span={3}>
|
||||
<span style={{fontSize: 28}}>
|
||||
{product?.displayName}
|
||||
</span>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Detail")}><span style={{fontSize: 16}}>{product?.detail}</span></Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Tag")}><span style={{fontSize: 16}}>{product?.tag}</span></Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:SKU")}><span style={{fontSize: 16}}>{product?.name}</span></Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Image")} span={3}>
|
||||
<img src={product?.image} alt={product?.image} height={90} style={{marginBottom: '20px'}}/>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Price")}>
|
||||
<span style={{fontSize: 28, color: "red", fontWeight: "bold"}}>
|
||||
{`${this.getCurrencySymbol(product)}${product?.price} (${this.getCurrencyText(product)})`}
|
||||
</span>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Quantity")}><span style={{fontSize: 16}}>{product?.quantity}</span></Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Sold")}><span style={{fontSize: 16}}>{product?.sold}</span></Descriptions.Item>
|
||||
<Descriptions.Item label={i18next.t("product:Pay")} span={3}>
|
||||
{
|
||||
this.renderPay(product)
|
||||
}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default ProductBuyPage;
|
@ -19,6 +19,7 @@ import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import ProductBuyPage from "./ProductBuyPage";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
@ -142,6 +143,16 @@ class ProductEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("product:Detail"), i18next.t("product:Detail - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.product.detail} onChange={e => {
|
||||
this.updateProductField('detail', e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("product:Currency"), i18next.t("product:Currency - Tooltip"))} :
|
||||
@ -218,10 +229,34 @@ class ProductEditPage extends React.Component {
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: '20px'}} >
|
||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Preview"), i18next.t("general:Preview - Tooltip"))} :
|
||||
</Col>
|
||||
{
|
||||
this.renderPreview()
|
||||
}
|
||||
</Row>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
renderPreview() {
|
||||
let buyUrl = `/products/${this.state.product.name}/buy`;
|
||||
return (
|
||||
<Col span={22} style={{display: "flex", flexDirection: "column"}}>
|
||||
<a style={{marginBottom: "10px", display: "flex"}} target="_blank" rel="noreferrer" href={buyUrl}>
|
||||
<Button type="primary">{i18next.t("product:Test buy page..")}</Button>
|
||||
</a>
|
||||
<br/>
|
||||
<br/>
|
||||
<div style={{width: "90%", border: "1px solid rgb(217,217,217)", boxShadow: "10px 10px 5px #888888", alignItems: "center", overflow: "auto", flexDirection: "column", flex: "auto"}}>
|
||||
<ProductBuyPage product={this.state.product} />
|
||||
</div>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
|
||||
submitProductEdit(willExist) {
|
||||
let product = Setting.deepCopy(this.state.product);
|
||||
ProductBackend.updateProduct(this.state.product.owner, this.state.productName, product)
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "Ressourcen"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "Alipay",
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Edit Product": "Edit Product",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "Price",
|
||||
"Price - Tooltip": "Price - Tooltip",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip"
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||
"USD": "USD",
|
||||
"WeChat Pay": "WeChat Pay"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "Zugangsschlüssel",
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "Resources"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "Alipay",
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Edit Product": "Edit Product",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "Price",
|
||||
"Price - Tooltip": "Price - Tooltip",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip"
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||
"USD": "USD",
|
||||
"WeChat Pay": "WeChat Pay"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "Access key",
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "Ressource"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "Alipay",
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Edit Product": "Edit Product",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "Price",
|
||||
"Price - Tooltip": "Price - Tooltip",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip"
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||
"USD": "USD",
|
||||
"WeChat Pay": "WeChat Pay"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "Clé d'accès",
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "リソース"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "Alipay",
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Edit Product": "Edit Product",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "Price",
|
||||
"Price - Tooltip": "Price - Tooltip",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip"
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||
"USD": "USD",
|
||||
"WeChat Pay": "WeChat Pay"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "アクセスキー",
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "Resources"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "Alipay",
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Edit Product": "Edit Product",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "Price",
|
||||
"Price - Tooltip": "Price - Tooltip",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip"
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||
"USD": "USD",
|
||||
"WeChat Pay": "WeChat Pay"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "Access key",
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "Ресурсы"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "Alipay",
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Edit Product": "Edit Product",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "Price",
|
||||
"Price - Tooltip": "Price - Tooltip",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip"
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||
"USD": "USD",
|
||||
"WeChat Pay": "WeChat Pay"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "Ключ доступа",
|
||||
|
@ -272,22 +272,35 @@
|
||||
"Resources": "资源"
|
||||
},
|
||||
"product": {
|
||||
"Alipay": "支付宝",
|
||||
"Buy Product": "购买商品",
|
||||
"CNY": "人民币",
|
||||
"Currency": "币种",
|
||||
"Currency - Tooltip": "币种 - 工具提示",
|
||||
"Detail": "详情",
|
||||
"Detail - Tooltip": "详情 - 工具提示",
|
||||
"Edit Product": "编辑商品",
|
||||
"Image": "图片",
|
||||
"Image - Tooltip": "图片 - 工具提示",
|
||||
"New Product": "添加商品",
|
||||
"Pay": "支付方式",
|
||||
"Payment providers": "支付提供商",
|
||||
"Payment providers - Tooltip": "支付提供商 - 工具提示",
|
||||
"Paypal": "Paypal",
|
||||
"Price": "价格",
|
||||
"Price - Tooltip": "价格 - 工具提示",
|
||||
"Quantity": "库存",
|
||||
"Quantity - Tooltip": "库存 - 工具提示",
|
||||
"SKU": "货号",
|
||||
"Sold": "售出",
|
||||
"Sold - Tooltip": "售出 - 工具提示",
|
||||
"Tag": "标签",
|
||||
"Tag - Tooltip": "标签 - 工具提示"
|
||||
"Tag": "类别",
|
||||
"Tag - Tooltip": "类别 - 工具提示",
|
||||
"Test buy page..": "测试购买页面..",
|
||||
"There is no payment channel for this product.": "该商品没有付款方式。",
|
||||
"This product is currently not in sale.": "该商品目前未在售。",
|
||||
"USD": "美元",
|
||||
"WeChat Pay": "微信支付"
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "访问密钥",
|
||||
|
Loading…
x
Reference in New Issue
Block a user