mirror of
https://github.com/rustdesk/doc.rustdesk.com.git
synced 2026-04-21 15:40:28 +00:00
select currency
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
ln -s careers/index.html careers.html
|
||||
ln -s open-source/index.html open-source.html
|
||||
ln -s ../v2/self-host
|
||||
ln -s ../currencies.json
|
||||
ln -s ../v2/web
|
||||
cp -rf ../zh ./
|
||||
tar czf x *
|
||||
|
||||
@@ -5,17 +5,29 @@ import Headline from '~/components/ui/Headline.astro';
|
||||
import WidgetWrapper from '~/components/ui/WidgetWrapper.astro';
|
||||
import type { Pricing as Props } from '~/types';
|
||||
|
||||
const defaultCurrencyCopy = {
|
||||
title: 'Select payment currency',
|
||||
label: 'Payment currency',
|
||||
tip: 'The currency you choose will also be used on your invoice.',
|
||||
emailTip: 'After successful payment, you will receive your invoice and license by email. Please enter the correct email address on the next payment page.',
|
||||
businessTip: 'If you need a business invoice with your business name and tax number, please check the "I\'m purchasing as a business" checkbox on the next payment page.',
|
||||
confirm: 'Continue to checkout',
|
||||
cancel: 'Cancel',
|
||||
} as const;
|
||||
|
||||
const {
|
||||
title = '',
|
||||
subtitle = '',
|
||||
tagline = '',
|
||||
prices = [],
|
||||
currencyCopy = defaultCurrencyCopy,
|
||||
|
||||
id,
|
||||
isDark = false,
|
||||
classes = {},
|
||||
bg = await Astro.slots.render('bg'),
|
||||
} = Astro.props;
|
||||
const defaultCurrency = 'USD';
|
||||
---
|
||||
|
||||
<WidgetWrapper id={id} isDark={isDark} containerClass={`max-w-7xl mx-auto ${classes?.container ?? ''}`} bg={bg}>
|
||||
@@ -29,8 +41,8 @@ const {
|
||||
>
|
||||
{
|
||||
prices &&
|
||||
prices.map(
|
||||
({
|
||||
prices.map((priceItem, index) => {
|
||||
const {
|
||||
title,
|
||||
subtitle,
|
||||
price,
|
||||
@@ -42,7 +54,9 @@ const {
|
||||
content,
|
||||
id,
|
||||
ribbonTitle,
|
||||
}) => (
|
||||
} = priceItem;
|
||||
|
||||
return (
|
||||
<div
|
||||
class="col-span-3 mx-auto flex w-full sm:col-span-1 md:col-span-1 lg:col-span-1 xl:col-span-1"
|
||||
id={id || ''}
|
||||
@@ -69,11 +83,16 @@ const {
|
||||
</p>
|
||||
)}
|
||||
<div class="my-6">
|
||||
<div class="flex items-center justify-center text-center mb-1">
|
||||
<span class="text-5xl">$</span>
|
||||
<span class="text-5xl font-extrabold">
|
||||
<Fragment set:html={price} />
|
||||
</span>
|
||||
<div class="mb-1 flex justify-center text-center">
|
||||
<div class="relative inline-flex items-end justify-center gap-1.5">
|
||||
<span class="text-5xl">$</span>
|
||||
<span class="text-5xl font-extrabold">
|
||||
<Fragment set:html={price} />
|
||||
</span>
|
||||
<span class="pointer-events-none absolute -right-7 top-1 text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-400 dark:text-slate-500">
|
||||
USD
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-base leading-6 lowercase text-gray-600 dark:text-slate-400">{period}</span>
|
||||
</div>
|
||||
@@ -96,36 +115,236 @@ const {
|
||||
)}
|
||||
</div>
|
||||
{content && <Fragment set:html={content} />}
|
||||
{callToAction && (
|
||||
<div class={`flex justify-center`}>
|
||||
{typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
callToAction &&
|
||||
(callToAction.href || callToAction.onclick) && (
|
||||
<Button {...(hasRibbon ? { variant: 'primary' } : {})} {...callToAction} />
|
||||
)
|
||||
{(callToAction || callToAction2) && (
|
||||
<div class="mt-4 space-y-3">
|
||||
{callToAction && (
|
||||
<div class={`flex justify-center`}>
|
||||
{typeof callToAction === 'string' ? (
|
||||
<Fragment set:html={callToAction} />
|
||||
) : (
|
||||
callToAction &&
|
||||
(callToAction.href || callToAction.onclick) && (
|
||||
<Button {...(hasRibbon ? { variant: 'primary' } : {})} {...callToAction} />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{callToAction2 && (
|
||||
<div class={`flex justify-center`}>
|
||||
{typeof callToAction2 === 'string' ? (
|
||||
<Fragment set:html={callToAction2} />
|
||||
) : (
|
||||
callToAction2 &&
|
||||
(callToAction2.href || callToAction2.onclick) && (
|
||||
<Button {...(hasRibbon ? { variant: 'primary' } : {})} {...callToAction2} />
|
||||
)
|
||||
{callToAction2 && (
|
||||
<div class={`flex justify-center`}>
|
||||
{typeof callToAction2 === 'string' ? (
|
||||
<Fragment set:html={callToAction2} />
|
||||
) : (
|
||||
callToAction2 &&
|
||||
(callToAction2.href || callToAction2.onclick) && (
|
||||
<Button {...(hasRibbon ? { variant: 'primary' } : {})} {...callToAction2} />
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
)
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</WidgetWrapper>
|
||||
|
||||
<script is:inline define:vars={{ defaultCurrency, currencyCopy }}>
|
||||
(() => {
|
||||
const ns = (window.__pricing = window.__pricing || {});
|
||||
ns.defaultCurrency = defaultCurrency;
|
||||
ns.currencyCopy = currencyCopy;
|
||||
|
||||
if (ns.initialized) {
|
||||
ns.loadCurrencies?.();
|
||||
return;
|
||||
}
|
||||
ns.initialized = true;
|
||||
|
||||
const CHECKOUT_PATH = '/api/lic/stripe/checkout';
|
||||
const CURRENCIES_URL = '/currencies.json';
|
||||
const CURRENCY_RE = /^[A-Z]{3}$/;
|
||||
|
||||
const normalize = (v) => {
|
||||
const s = String(v || '').trim().toUpperCase();
|
||||
return CURRENCY_RE.test(s) ? s : '';
|
||||
};
|
||||
|
||||
const getPageCurrency = () => normalize(new URLSearchParams(location.search).get('currency'));
|
||||
|
||||
const getLoadedCurrencies = () => (Array.isArray(ns.currencies) ? ns.currencies : []);
|
||||
|
||||
const currencyByRegion = {
|
||||
AT: 'EUR', AU: 'AUD', BE: 'EUR', BR: 'BRL', CA: 'CAD', CH: 'CHF',
|
||||
CN: 'CNY', CY: 'EUR', CZ: 'CZK', DE: 'EUR', DK: 'DKK', EE: 'EUR',
|
||||
ES: 'EUR', FI: 'EUR', FR: 'EUR', GB: 'GBP', GR: 'EUR', HK: 'HKD',
|
||||
HR: 'EUR', HU: 'HUF', ID: 'IDR', IE: 'EUR', IL: 'ILS', IN: 'INR',
|
||||
IS: 'ISK', IT: 'EUR', JP: 'JPY', KR: 'KRW', LT: 'EUR', LU: 'EUR',
|
||||
LV: 'EUR', MT: 'EUR', MX: 'MXN', MY: 'MYR', NL: 'EUR', NO: 'NOK',
|
||||
NZ: 'NZD', PH: 'PHP', PL: 'PLN', PT: 'EUR', RO: 'RON', SE: 'SEK',
|
||||
SG: 'SGD', SI: 'EUR', SK: 'EUR', TH: 'THB', TR: 'TRY', US: 'USD',
|
||||
ZA: 'ZAR',
|
||||
};
|
||||
|
||||
const getRegionFromLocale = (v) => {
|
||||
const s = String(v || '').trim();
|
||||
if (!s) return '';
|
||||
try {
|
||||
if (typeof Intl?.Locale === 'function') {
|
||||
const loc = new Intl.Locale(s);
|
||||
return loc.region || loc.maximize().region || '';
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
const m = s.match(/-([a-z]{2}|\d{3})(?:-|$)/i);
|
||||
return m?.[1]?.toUpperCase() ?? '';
|
||||
};
|
||||
|
||||
const getBrowserLocaleCurrency = () => {
|
||||
const currencies = getLoadedCurrencies();
|
||||
if (!currencies.length) return '';
|
||||
const locales = Array.isArray(navigator.languages) && navigator.languages.length
|
||||
? navigator.languages : [navigator.language];
|
||||
for (const locale of locales) {
|
||||
const region = getRegionFromLocale(locale);
|
||||
const inferred = normalize(currencyByRegion[region]);
|
||||
if (inferred && currencies.includes(inferred)) return inferred;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
const getFallbackCurrency = (requested) => {
|
||||
const direct = normalize(requested);
|
||||
const currencies = getLoadedCurrencies();
|
||||
if (direct && (!currencies.length || currencies.includes(direct))) return direct;
|
||||
const page = getPageCurrency();
|
||||
if (page && (!currencies.length || currencies.includes(page))) return page;
|
||||
const browser = getBrowserLocaleCurrency();
|
||||
if (browser) return browser;
|
||||
return normalize(ns.defaultCurrency) || 'USD';
|
||||
};
|
||||
|
||||
window.getSelectedCurrency = () => normalize(ns.selectedCurrency) || getFallbackCurrency();
|
||||
|
||||
ns.loadCurrencies = () => {
|
||||
if (getLoadedCurrencies().length) return ns.currenciesPromise ?? Promise.resolve(ns.currencies);
|
||||
if (!ns.currenciesPromise) {
|
||||
ns.currenciesPromise = fetch(CURRENCIES_URL, { cache: 'no-store' })
|
||||
.then((r) => { if (!r.ok) throw new Error(r.status); return r.json(); })
|
||||
.then((data) => {
|
||||
ns.currencies = Array.isArray(data)
|
||||
? data.map((c) => normalize(c)).filter(Boolean).sort()
|
||||
: [];
|
||||
return ns.currencies;
|
||||
})
|
||||
.catch(() => { ns.currencies = undefined; return undefined; })
|
||||
.finally(() => { ns.currenciesPromise = undefined; });
|
||||
}
|
||||
return ns.currenciesPromise;
|
||||
};
|
||||
|
||||
const buildCheckoutUrl = (rawUrl, currency) => {
|
||||
const url = new URL(String(rawUrl), location.origin);
|
||||
new URLSearchParams(location.search).forEach((v, k) => {
|
||||
if (k !== 'currency' && !url.searchParams.has(k)) url.searchParams.append(k, v);
|
||||
});
|
||||
if (currency === 'USD') url.searchParams.delete('currency');
|
||||
else url.searchParams.set('currency', currency.toLowerCase());
|
||||
return url.toString();
|
||||
};
|
||||
|
||||
const openCurrencyDialog = async (pending) => {
|
||||
const Swal = ns.swal;
|
||||
const currencies = getLoadedCurrencies();
|
||||
if (!Swal?.fire || !currencies.length) {
|
||||
return ns.nativeOpen?.(
|
||||
buildCheckoutUrl(pending.url, getFallbackCurrency(pending.preferredCurrency)),
|
||||
pending.target, pending.features
|
||||
);
|
||||
}
|
||||
|
||||
const copy = ns.currencyCopy || currencyCopy;
|
||||
const fallback = currencies.find((c) => c === getFallbackCurrency(pending.preferredCurrency)) || currencies[0];
|
||||
const selectId = 'pricing-currency-swal-select';
|
||||
const options = currencies
|
||||
.map((c) => `<option value="${c}"${c === fallback ? ' selected' : ''}>${c}</option>`)
|
||||
.join('');
|
||||
const infoIcon = '<svg style="margin-top:0.1rem;width:0.85rem;height:0.85rem;flex-shrink:0;color:#94a3b8;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z" clip-rule="evenodd" /></svg>';
|
||||
|
||||
const result = await Swal.fire({
|
||||
title: copy.title,
|
||||
html:
|
||||
'<div style="margin-top:0.25rem;text-align:left;">' +
|
||||
'<div style="position:relative;">' +
|
||||
'<select id="' + selectId + '" aria-label="' + copy.label + '"' +
|
||||
' style="width:100%;appearance:none;-webkit-appearance:none;border:1px solid rgba(148,163,184,0.4);border-radius:0.75rem;background:#fff;padding:0.75rem 2.5rem 0.75rem 0.95rem;font-size:0.95rem;line-height:1.4;color:#0f172a;box-shadow:0 1px 3px rgba(15,23,42,0.06);outline:none;transition:border-color 0.15s,box-shadow 0.15s;cursor:pointer;"' +
|
||||
" onfocus=\"this.style.borderColor='#6366f1';this.style.boxShadow='0 0 0 3px rgba(99,102,241,0.12)'\"" +
|
||||
" onblur=\"this.style.borderColor='rgba(148,163,184,0.4)';this.style.boxShadow='0 1px 3px rgba(15,23,42,0.06)'\"" +
|
||||
'>' + options + '</select>' +
|
||||
'<svg style="pointer-events:none;position:absolute;right:0.75rem;top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:#94a3b8;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /></svg>' +
|
||||
'</div>' +
|
||||
'<p style="margin:0.75rem 0 0;display:flex;align-items:flex-start;gap:0.35rem;font-size:0.78rem;line-height:1.55;color:#64748b;">' + infoIcon + '<span>' + copy.emailTip + '</span></p>' +
|
||||
'<p style="margin:0.45rem 0 0;display:flex;align-items:flex-start;gap:0.35rem;font-size:0.78rem;line-height:1.55;color:#64748b;">' + infoIcon + '<span>' + copy.tip + '</span></p>' +
|
||||
'<p style="margin:0.45rem 0 0;display:flex;align-items:flex-start;gap:0.35rem;font-size:0.78rem;line-height:1.55;color:#64748b;">' + infoIcon + '<span>' + copy.businessTip + '</span></p>' +
|
||||
'</div>',
|
||||
showCancelButton: true,
|
||||
reverseButtons: true,
|
||||
confirmButtonText: copy.confirm,
|
||||
cancelButtonText: copy.cancel,
|
||||
focusConfirm: true,
|
||||
preConfirm: () => {
|
||||
const select = document.getElementById(selectId);
|
||||
if (!(select instanceof HTMLSelectElement)) return fallback;
|
||||
return normalize(select.value) || fallback;
|
||||
},
|
||||
});
|
||||
|
||||
if (!result.isConfirmed) return null;
|
||||
const selected = normalize(result.value) || fallback;
|
||||
ns.selectedCurrency = selected;
|
||||
return ns.nativeOpen?.(buildCheckoutUrl(pending.url, selected), pending.target, pending.features);
|
||||
};
|
||||
|
||||
if (!ns.openPatched) {
|
||||
ns.openPatched = true;
|
||||
var nativeOpen = window.open.bind(window);
|
||||
ns.nativeOpen = nativeOpen;
|
||||
|
||||
window.open = function (url, target, features) {
|
||||
try {
|
||||
var parsed = new URL(String(url), location.origin);
|
||||
if (parsed.pathname.startsWith(CHECKOUT_PATH)) {
|
||||
var pending = {
|
||||
url: parsed.toString(),
|
||||
target: target,
|
||||
features: features,
|
||||
preferredCurrency: normalize(parsed.searchParams.get('currency')),
|
||||
};
|
||||
var load = ns.loadCurrencies?.();
|
||||
if (load?.finally) {
|
||||
load.finally(function () { openCurrencyDialog(pending); });
|
||||
return null;
|
||||
}
|
||||
openCurrencyDialog(pending);
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('pricing: failed to intercept checkout URL', e);
|
||||
}
|
||||
return nativeOpen(url, target, features);
|
||||
};
|
||||
}
|
||||
|
||||
ns.selectedCurrency = getPageCurrency() || undefined;
|
||||
ns.loadCurrencies();
|
||||
|
||||
document.addEventListener('astro:after-swap', () => {
|
||||
ns.defaultCurrency = defaultCurrency;
|
||||
ns.currencyCopy = currencyCopy;
|
||||
ns.loadCurrencies?.();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -70,17 +70,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'اختر عملة الدفع',
|
||||
label: 'عملة الدفع',
|
||||
tip: 'العملة التي تختارها ستُستخدم أيضًا في فاتورتك.',
|
||||
emailTip: 'بعد إتمام الدفع بنجاح، ستتلقى الفاتورة والترخيص عبر البريد الإلكتروني. يرجى إدخال عنوان البريد الإلكتروني الصحيح في صفحة الدفع التالية.',
|
||||
businessTip: 'إذا كنت بحاجة إلى فاتورة عمل تتضمن اسم الشركة ورقمها الضريبي، فيرجى تحديد مربع الاختيار "أقوم بالشراء بصفتي شركة" في صفحة الدفع التالية.',
|
||||
confirm: 'متابعة إلى الدفع',
|
||||
cancel: 'إلغاء',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'يرجى التأكيد',
|
||||
html: `<p style="text-align:right">هل تريد المتابعة إلى صفحة الشراء؟ <br><br>يرجى ملاحظة أن ما تشتريه <b style="font-size: 2em">ليس</b> اشتراكًا في <span style="text-decoration:line-through">خدمة البرمجيات كخدمة (SaaS)</span>. <br><br>بدلاً من ذلك، إنه ترخيص لحل <b style="font-size: 2em">استضافة ذاتية</b>، والذي يتطلب منك نشره على خادمك الخاص (خادم سحابي، مثل AWS EC2 أو Azure VM أو Vultr VPS إلخ، أو خادمك المحلي). <br><br>يرجى <b style="font-size: 2em">عدم</b> الشراء إذا كنت لا تعرف ما هي الاستضافة الذاتية`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'نعم',
|
||||
cancelButtonText: 'لا',
|
||||
}).then((result) => {
|
||||
@@ -88,7 +99,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'يرجى التأكيد',
|
||||
html: `يرجى ملاحظة أننا <span class="text-3xl font-bold">لا</span> نقدم <span class="text-3xl font-bold">استردادًا للأموال</span>. نوصي بشدة <span class="underline font-bold">باختبار خطتنا المجانية للاستضافة الذاتية</span> قبل التفكير في شراء خطتنا الاحترافية. هل ما زلت مهتمًا بالمتابعة؟`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'نعم',
|
||||
cancelButtonText: 'لا',
|
||||
}).then((result) => {
|
||||
@@ -120,6 +131,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='تسعير حلول <span class="text-5xl text-blue-500">الاستضافة الذاتية</span> لدينا'
|
||||
subtitle="ادفع فقط مقابل ما تحتاجه"
|
||||
prices={[
|
||||
@@ -276,6 +288,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'مخصص V2',
|
||||
|
||||
@@ -72,17 +72,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'Zahlungswährung auswählen',
|
||||
label: 'Zahlungswährung',
|
||||
tip: 'Die von Ihnen gewählte Währung wird auch auf Ihrer Rechnung verwendet.',
|
||||
emailTip: 'Bitte geben Sie auf der folgenden Zahlungsseite die richtige E-Mail-Adresse an, da Sie Ihre Rechnung und Lizenz nach erfolgreicher Zahlung per E-Mail erhalten.',
|
||||
businessTip: 'Wenn Sie eine Geschäftsrechnung mit Firmenname und Steuernummer benötigen, aktivieren Sie bitte auf der folgenden Zahlungsseite das Kontrollkästchen "Ich kaufe als Unternehmen".',
|
||||
confirm: 'Zur Kasse',
|
||||
cancel: 'Abbrechen',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'Bitte bestätigen',
|
||||
html: '<p style="text-align:left">Möchten Sie zur Kaufseite weitergeleitet werden? <br><br>Bitte beachten Sie, dass Sie <b style="font-size: 2em">KEIN</b> <span style="text-decoration:line-through">SaaS (Software as a Service) Abonnement</span> erwerben. <br><br>Stattdessen handelt es sich um eine Lizenz für eine <b style="font-size: 2em">Self-Hosting</b> Lösung, die Sie auf Ihrem eigenen Server bereitstellen müssen (Cloud-Server, z.B. AWS EC2, Azure VM, Vultr VPS etc. oder Ihr eigener On-Premise-Server). <br><br>Bitte <b style="font-size: 2em">kaufen Sie nicht</b>, wenn Sie nicht wissen, was Self-Hosting bedeutet.',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Ja',
|
||||
cancelButtonText: 'Nein',
|
||||
}).then((result) => {
|
||||
@@ -90,7 +101,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'Bitte bestätigen',
|
||||
html: 'Bitte beachten Sie, dass wir <span class="text-3xl font-bold">keine</span> <span class="text-3xl font-bold">Rückerstattungen</span> anbieten. Wir empfehlen dringend, <span class="underline font-bold">unseren kostenlosen Self-Hosting-Plan zu testen</span>, bevor Sie den Kauf unseres Pro-Plans in Erwägung ziehen. Möchten Sie trotzdem fortfahren?',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Ja',
|
||||
cancelButtonText: 'Nein',
|
||||
}).then((result) => {
|
||||
@@ -122,6 +133,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='Preise für unsere <span class="text-5xl text-blue-500">Self-Hosting</span> Lösungen'
|
||||
subtitle="Zahlen Sie nur für das, was Sie benötigen"
|
||||
prices={[
|
||||
@@ -278,6 +290,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'Angepasst V2',
|
||||
|
||||
@@ -72,17 +72,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'Elige la moneda de pago',
|
||||
label: 'Moneda de pago',
|
||||
tip: 'La moneda que elijas también se usará en tu factura.',
|
||||
emailTip: 'Tras completar el pago con éxito, recibirás la factura y la licencia por correo electrónico. Introduce la dirección de correo correcta en la siguiente página de pago.',
|
||||
businessTip: 'Si necesitas una factura de empresa con el nombre de la empresa y el número fiscal, marca la casilla "Estoy comprando como empresa" en la siguiente página de pago.',
|
||||
confirm: 'Continuar al pago',
|
||||
cancel: 'Cancelar',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'Por favor, confirme',
|
||||
html: '<p style="text-align:left">¿Desea proceder a la página de compra? <br><br>Tenga en cuenta que lo que está comprando <b style="font-size: 2em">NO</b> es una suscripción <span style="text-decoration:line-through">SaaS (Software como Servicio)</span>. <br><br>En su lugar, es una licencia para una solución de <b style="font-size: 2em">alojamiento propio</b>, que requiere que la implemente en su propio servidor (servidor en la nube, por ejemplo, AWS EC2, Azure VM, Vultr VPS, etc., o su servidor local). <br><br>Por favor, <b style="font-size: 2em">no</b> compre si no sabe qué es el alojamiento propio',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Sí',
|
||||
cancelButtonText: 'No',
|
||||
}).then((result) => {
|
||||
@@ -90,7 +101,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'Por favor, confirme',
|
||||
html: 'Tenga en cuenta que <span class="text-3xl font-bold">no</span> ofrecemos <span class="text-3xl font-bold">reembolsos</span>. Recomendamos encarecidamente <span class="underline font-bold">probar nuestro plan gratuito de alojamiento propio</span> antes de considerar la compra de nuestro plan Pro. ¿Aún está interesado en continuar?',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Sí',
|
||||
cancelButtonText: 'No',
|
||||
}).then((result) => {
|
||||
@@ -122,6 +133,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='Precios de nuestras soluciones de <span class="text-5xl text-blue-500">alojamiento propio</span>'
|
||||
subtitle="Solo pague por lo que necesita"
|
||||
prices={[
|
||||
@@ -278,6 +290,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'Personalizado V2',
|
||||
|
||||
@@ -72,17 +72,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'Choisissez votre devise de paiement',
|
||||
label: 'Devise de paiement',
|
||||
tip: 'La devise choisie sera également utilisée sur votre facture.',
|
||||
emailTip: 'Une fois le paiement effectué, vous recevrez votre facture et votre licence par e-mail. Veuillez saisir la bonne adresse e-mail sur la page de paiement suivante.',
|
||||
businessTip: 'Si vous avez besoin d\'une facture professionnelle avec le nom de l\'entreprise et le numéro fiscal, cochez la case "J\'achète au nom d\'une entreprise" sur la page de paiement suivante.',
|
||||
confirm: 'Continuer vers le paiement',
|
||||
cancel: 'Annuler',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'Veuillez confirmer',
|
||||
html: '<p style="text-align:left">Voulez-vous procéder à la page d\'achat ? <br><br>Veuillez noter que ce que vous achetez <b style="font-size: 2em">N\'EST PAS</b> un abonnement <span style="text-decoration:line-through">SaaS (Logiciel en tant que Service)</span>. <br><br>Il s\'agit plutôt d\'une licence pour une solution <b style="font-size: 2em">auto-hébergée</b>, qui nécessite que vous la déployiez sur votre propre serveur (serveur cloud, par exemple AWS EC2, Azure VM, Vultr VPS, etc., ou votre serveur sur site). <br><br>Veuillez <b style="font-size: 2em">ne pas</b> acheter si vous ne savez pas ce qu\'est l\'auto-hébergement',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Oui',
|
||||
cancelButtonText: 'Non',
|
||||
}).then((result) => {
|
||||
@@ -90,7 +101,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'Veuillez confirmer',
|
||||
html: 'Veuillez noter que nous <span class="text-3xl font-bold">n\'offrons pas</span> de <span class="text-3xl font-bold">remboursements</span>. Nous vous recommandons fortement de <span class="underline font-bold">tester notre plan auto-hébergé gratuit</span> avant d\'envisager l\'achat de notre plan Pro. Êtes-vous toujours intéressé pour continuer ?',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Oui',
|
||||
cancelButtonText: 'Non',
|
||||
}).then((result) => {
|
||||
@@ -122,6 +133,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='Tarification de nos solutions <span class="text-5xl text-blue-500">auto-hébergées</span>'
|
||||
subtitle="Ne payez que pour ce dont vous avez besoin"
|
||||
prices={[
|
||||
@@ -278,6 +290,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'Personnalisé V2',
|
||||
|
||||
@@ -72,17 +72,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'Scegli la valuta di pagamento',
|
||||
label: 'Valuta di pagamento',
|
||||
tip: 'La valuta scelta verrà utilizzata anche nella fattura.',
|
||||
emailTip: "Dopo il pagamento andato a buon fine, riceverai fattura e licenza via e-mail. Inserisci l'indirizzo e-mail corretto nella pagina di pagamento successiva.",
|
||||
businessTip: 'Se hai bisogno di una fattura aziendale con ragione sociale e partita IVA, seleziona la casella "Sto acquistando come azienda" nella pagina di pagamento successiva.',
|
||||
confirm: 'Continua al pagamento',
|
||||
cancel: 'Annulla',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'Conferma per favore',
|
||||
html: `<p style="text-align:left">Vuoi procedere alla pagina di acquisto? <br><br>Si prega di notare che ciò che stai acquistando <b style="font-size: 2em">NON</b> è un abbonamento <span style="text-decoration:line-through">SaaS (Software as a Service)</span>. <br><br>Invece, è una licenza per una soluzione <b style="font-size: 2em">self-hosting</b>, che richiede di essere distribuita sul tuo server (server cloud, ad esempio AWS EC2, Azure VM, Vultr VPS ecc., o il tuo server on-premise). <br><br>Per favore <b style="font-size: 2em">non</b> acquistare se non sai cosa sia il self-hosting`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Sì',
|
||||
cancelButtonText: 'No',
|
||||
}).then((result) => {
|
||||
@@ -90,7 +101,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'Conferma per favore',
|
||||
html: `Si prega di notare che <span class="text-3xl font-bold">non</span> offriamo <span class="text-3xl font-bold">rimborsi</span>. Ti consigliamo vivamente di <span class="underline font-bold">testare il nostro piano gratuito di self-hosting</span> prima di considerare l'acquisto del nostro piano Pro. Sei ancora interessato a procedere?`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Sì',
|
||||
cancelButtonText: 'No',
|
||||
}).then((result) => {
|
||||
@@ -122,6 +133,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='Prezzi delle nostre soluzioni <span class="text-5xl text-blue-500">self-hosting</span>'
|
||||
subtitle="Paga solo per ciò di cui hai bisogno"
|
||||
prices={[
|
||||
@@ -278,6 +290,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'Personalizzato V2',
|
||||
|
||||
@@ -71,17 +71,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: '支払い通貨を選択',
|
||||
label: '支払い通貨',
|
||||
tip: '選択した通貨は、請求書でも使用されます。',
|
||||
emailTip: 'お支払い完了後、請求書とライセンスがメールで届きます。次の決済ページでは正しいメールアドレスを入力してください。',
|
||||
businessTip: '会社名と税番号入りの請求書が必要な場合は、次の決済ページで "事業者として購入する" のチェックボックスをオンにしてください。',
|
||||
confirm: '購入手続きへ進む',
|
||||
cancel: 'キャンセル',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: '確認してください',
|
||||
html: `<p style="text-align:left">購入ページに進みますか? <br><br>購入するものは<b style="font-size: 2em">決して</b> <span style="text-decoration:line-through">SaaS(サービスとしてのソフトウェア)</span>サブスクリプションではないことにご注意ください。 <br><br>代わりに、これは<b style="font-size: 2em">セルフホスティング</b>ソリューションのライセンスであり、自身のサーバー(クラウドサーバー、例えばAWS EC2、Azure VM、Vultr VPSなど、または自社のオンプレミスサーバー)にデプロイする必要があります。 <br><br>セルフホスティングが何かわからない場合は、<b style="font-size: 2em">購入しないでください</b>`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'はい',
|
||||
cancelButtonText: 'いいえ',
|
||||
}).then((result) => {
|
||||
@@ -89,7 +100,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: '確認してください',
|
||||
html: `当社は<span class="text-3xl font-bold">返金を行っていません</span>のでご注意ください。Proプランの購入を検討される前に、<span class="underline font-bold">無料のセルフホスティングプランをテスト</span>することを強くお勧めします。それでも進めますか?`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'はい',
|
||||
cancelButtonText: 'いいえ',
|
||||
}).then((result) => {
|
||||
@@ -121,6 +132,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='当社の<span class="text-5xl text-blue-500">セルフホスティング</span>ソリューションの料金'
|
||||
subtitle="必要なものにのみ支払う"
|
||||
prices={[
|
||||
@@ -277,6 +289,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'カスタマイズV2',
|
||||
|
||||
@@ -69,17 +69,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: '결제 통화 선택',
|
||||
label: '결제 통화',
|
||||
tip: '선택한 통화는 인보이스에도 사용됩니다.',
|
||||
emailTip: '결제가 완료되면 인보이스와 라이선스가 이메일로 발송됩니다. 다음 결제 페이지에서 올바른 이메일 주소를 입력해 주세요.',
|
||||
businessTip: '회사명과 세금 번호가 포함된 사업자용 인보이스가 필요하면 다음 결제 페이지에서 "사업자로 구매합니다" 체크박스를 선택해 주세요.',
|
||||
confirm: '결제로 계속',
|
||||
cancel: '취소',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: '확인해 주세요',
|
||||
html: `<p style="text-align:left">구매 페이지로 진행하시겠습니까? <br><br>구매하시는 것은 <b style="font-size: 2em">SaaS(서비스형 소프트웨어)</b> 구독이 아닌 <b style="font-size: 2em">자체 호스팅</b> 솔루션의 라이센스입니다. 이 솔루션은 귀하의 서버(클라우드 서버, 예: AWS EC2, Azure VM, Vultr VPS 등)에서 배포해야 합니다. <br><br>자체 호스팅이 무엇인지 모른다면 <b style="font-size: 2em">구매하지 마세요</b>`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '예',
|
||||
cancelButtonText: '아니오',
|
||||
}).then((result) => {
|
||||
@@ -87,7 +98,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: '확인해 주세요',
|
||||
html: `환불을 <span class="text-3xl font-bold">제공하지 않습니다</span>. 구매하기 전에 <span class="underline font-bold">무료 자체 호스팅 계획을 테스트</span>하는 것을 강력히 권장합니다. 계속 진행하시겠습니까?`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '예',
|
||||
cancelButtonText: '아니오',
|
||||
}).then((result) => {
|
||||
@@ -119,6 +130,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='우리의 <span class="text-5xl text-blue-500">자체 호스팅</span> 솔루션 가격'
|
||||
subtitle="필요한 만큼만 지불하세요"
|
||||
prices={[
|
||||
@@ -275,6 +287,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: '맞춤형 V2',
|
||||
|
||||
@@ -71,17 +71,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
question: item.title,
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'Select payment currency',
|
||||
label: 'Payment currency',
|
||||
tip: 'The currency you choose will also be used on your invoice.',
|
||||
emailTip: 'After successful payment, you will receive your invoice and license by email. Please enter the correct email address on the next payment page.',
|
||||
businessTip: 'If you need a business invoice with your business name and tax number, please check the "I\'m purchasing as a business" checkbox on the next payment page.',
|
||||
confirm: 'Continue to checkout',
|
||||
cancel: 'Cancel',
|
||||
};
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'Please Confirm',
|
||||
html: `<p style="text-align:left">Do you want to proceed to the purchase page? <br><br>Please note that what you are purchasing is <b style="font-size: 2em">NOT</b> a <span style="text-decoration:line-through">SaaS(Software as a Service)</span> subscription. <br><br>Instead, it is a license for a <b style="font-size: 2em">self-hosting</b> solution, which requires you to deploy it on your own server (cloud server, e.g. AWS EC2, Azure VM, Vultr VPS etc, or your on-premise server). <br><br>Please <b style="font-size: 2em">don't</b> buy if you don't know what is self-hosting`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Yes',
|
||||
cancelButtonText: 'No',
|
||||
}).then((result) => {
|
||||
@@ -89,7 +100,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'Please Confirm',
|
||||
html: `Please note that we <span class="text-3xl font-bold">don't</span> offer <span class="text-3xl font-bold">refunds</span>. We strongly recommend <span class="underline font-bold">testing our free self-hosting plan</span> before considering the purchase of our Pro plan. Are you still interested in proceeding?`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Yes',
|
||||
cancelButtonText: 'No',
|
||||
}).then((result) => {
|
||||
@@ -122,6 +133,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='Pricing of our <span class="text-5xl text-blue-500">self-hosting</span> solutions'
|
||||
subtitle="Only pay for what you need"
|
||||
prices={[
|
||||
@@ -278,6 +290,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'Customized V2',
|
||||
|
||||
@@ -72,17 +72,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: 'Escolha a moeda de pagamento',
|
||||
label: 'Moeda de pagamento',
|
||||
tip: 'A moeda escolhida também será usada na sua fatura.',
|
||||
emailTip: 'Após a confirmação do pagamento, você receberá a fatura e a licença por e-mail. Informe o endereço de e-mail correto na próxima página de pagamento.',
|
||||
businessTip: 'Se você precisa de uma fatura empresarial com o nome da empresa e o número fiscal, marque a caixa "Estou comprando como empresa" na próxima página de pagamento.',
|
||||
confirm: 'Continuar para o checkout',
|
||||
cancel: 'Cancelar',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: 'Por favor, confirme',
|
||||
html: `<p style="text-align:left">Deseja prosseguir para a página de compra? <br><br>Por favor, note que o que você está comprando <b style="font-size: 2em">NÃO</b> é uma assinatura de <span style="text-decoration:line-through">SaaS (Software como Serviço)</span>. <br><br>Em vez disso, é uma licença para uma solução de <b style="font-size: 2em">auto-hospedagem</b>, que requer que você a implante em seu próprio servidor (servidor na nuvem, por exemplo, AWS EC2, Azure VM, Vultr VPS etc., ou seu servidor local). <br><br>Por favor, <b style="font-size: 2em">não</b> compre se você não sabe o que é auto-hospedagem`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Sim',
|
||||
cancelButtonText: 'Não',
|
||||
}).then((result) => {
|
||||
@@ -90,7 +101,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: 'Por favor, confirme',
|
||||
html: `Por favor, note que <span class="text-3xl font-bold">não</span> oferecemos <span class="text-3xl font-bold">reembolsos</span>. Recomendamos fortemente <span class="underline font-bold">testar nosso plano gratuito de auto-hospedagem</span> antes de considerar a compra do nosso plano Pro. Você ainda está interessado em prosseguir?`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: 'Sim',
|
||||
cancelButtonText: 'Não',
|
||||
}).then((result) => {
|
||||
@@ -122,6 +133,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='Preços de nossas soluções de <span class="text-5xl text-blue-500">auto-hospedagem</span>'
|
||||
subtitle="Pague apenas pelo que você precisa"
|
||||
prices={[
|
||||
@@ -278,6 +290,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: 'Personalizado V2',
|
||||
|
||||
@@ -69,17 +69,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: '选择付款货币',
|
||||
label: '付款货币',
|
||||
tip: '你选择的货币也会用于发票。',
|
||||
emailTip: '付款成功后,你将通过邮箱收到发票和许可证。请在接下来的付款页面填写正确的邮箱地址。',
|
||||
businessTip: '如果你需要包含公司名称和税号的企业发票,请在接下来的付款页面勾选 "我正在以企业身份购买" 复选框。',
|
||||
confirm: '继续购买',
|
||||
cancel: '取消',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: '请确认',
|
||||
html: '<p style="text-align:left">您是否要继续前往购买页面?<br><br>请注意,您购买的<b style="font-size: 2em">不是</b> <span style="text-decoration:line-through">SaaS(软件即服务)</span> 订阅。<br><br>相反,这是一个 <b style="font-size: 2em">自托管</b> 解决方案的许可证,您需要将其部署在您自己的服务器上(云服务器,例如 AWS EC2、Azure VM、Vultr VPS 等,或您的本地服务器)。<br><br>如果您不知道什么是自托管,请<b style="font-size: 2em">不要</b>购买。',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
}).then((result) => {
|
||||
@@ -87,15 +98,13 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: '请确认',
|
||||
html: '请注意,我们 <span class="text-3xl font-bold">不</span> 提供 <span class="text-3xl font-bold">退款</span>。我们强烈建议在考虑购买我们的专业版计划之前,<span class="underline font-bold">测试我们的免费自托管计划</span>。您是否仍然有兴趣继续?',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
try {
|
||||
const url = new URL(redirectUrl);
|
||||
// Ensure currency=cny for zh-cn
|
||||
if (!url.searchParams.has('currency')) url.searchParams.set('currency', 'cny');
|
||||
const pageParams = new URLSearchParams(window.location.search);
|
||||
pageParams.forEach((value, key) => {
|
||||
if (!url.searchParams.has(key)) url.searchParams.append(key, value);
|
||||
@@ -105,8 +114,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
const qs = window.location.search
|
||||
? (redirectUrl.includes('?') ? '&' : '?') + window.location.search.slice(1)
|
||||
: '';
|
||||
const sep = (redirectUrl + qs).includes('?') ? '&' : '?';
|
||||
window.open(redirectUrl + qs + sep + 'currency=cny', '_blank');
|
||||
window.open(redirectUrl + qs, '_blank');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -124,6 +132,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
<!-- Pricing Widget ******************* -->
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='我们的 <span class="text-5xl text-blue-500">自托管</span> 解决方案的定价'
|
||||
subtitle="按需付费"
|
||||
prices={[
|
||||
@@ -280,6 +289,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: '定制版 V2',
|
||||
|
||||
@@ -67,17 +67,28 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
answer: item.description.replace(/<[^>]*>/g, ''),
|
||||
}));
|
||||
|
||||
const currencyCopy = {
|
||||
title: '選擇付款貨幣',
|
||||
label: '付款貨幣',
|
||||
tip: '你選擇的貨幣也會用於發票。',
|
||||
emailTip: '付款成功後,你將透過電子郵件收到發票和授權。請在接下來的付款頁面填寫正確的電子郵件地址。',
|
||||
businessTip: '如果你需要包含公司名稱和稅號的企業發票,請在接下來的付款頁面勾選 "我正以企業身分購買" 核取方塊。',
|
||||
confirm: '繼續購買',
|
||||
cancel: '取消',
|
||||
};
|
||||
|
||||
---
|
||||
|
||||
<script>
|
||||
import Swal from 'sweetalert2';
|
||||
import 'sweetalert2/dist/sweetalert2.min.css';
|
||||
(window.__pricing = window.__pricing || {}).swal = Swal;
|
||||
window['gotoBuy'] = function (redirectUrl) {
|
||||
Swal.fire({
|
||||
title: '請確認',
|
||||
html: `<p style="text-align:left">您確定要前往購買頁面嗎?<br><br>請注意,您購買的<b style="font-size: 2em">不是</b><span style="text-decoration:line-through">SaaS(軟體即服務)</span>訂閱。<br><br>相反,這是一個<b style="font-size: 2em">自託管</b>解決方案的授權,需要您在自己的伺服器上部署(雲端伺服器,如AWS EC2、Azure VM、Vultr VPS等,或您的本地伺服器)。<br><br>如果您不了解什麼是自託管,請<b style="font-size: 2em">不要</b>購買。`,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
}).then((result) => {
|
||||
@@ -85,7 +96,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
Swal.fire({
|
||||
title: '請確認',
|
||||
html: `請注意,我們<span class="text-3xl font-bold">不提供</span><span class="text-3xl font-bold">退款</span>。我們強烈建議您在考慮購買我們的Pro計劃之前,<span class="underline font-bold">先試用我們的免費自託管計劃</span>。您仍然想要繼續嗎?`,
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
}).then((result) => {
|
||||
@@ -117,6 +128,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
title='我們的<span class="text-5xl text-blue-500">自託管</span>解決方案價格'
|
||||
subtitle="只為您所需付費"
|
||||
prices={[
|
||||
@@ -273,6 +285,7 @@ const faqItems = faqRawItems.map((item) => ({
|
||||
/>
|
||||
|
||||
<Prices
|
||||
currencyCopy={currencyCopy}
|
||||
prices={[
|
||||
{
|
||||
title: '自定義 V2',
|
||||
|
||||
11
v3/src/types.d.ts
vendored
11
v3/src/types.d.ts
vendored
@@ -233,8 +233,19 @@ export interface Stats extends Omit<Headline, 'classes'>, Widget {
|
||||
stats?: Array<Stat>;
|
||||
}
|
||||
|
||||
export interface PricingCurrencyCopy {
|
||||
title: string;
|
||||
label: string;
|
||||
tip: string;
|
||||
emailTip: string;
|
||||
businessTip: string;
|
||||
confirm: string;
|
||||
cancel: string;
|
||||
}
|
||||
|
||||
export interface Pricing extends Omit<Headline, 'classes'>, Widget {
|
||||
prices?: Array<Price>;
|
||||
currencyCopy?: PricingCurrencyCopy;
|
||||
}
|
||||
|
||||
export interface Testimonials extends Omit<Headline, 'classes'>, Widget {
|
||||
|
||||
@@ -840,7 +840,7 @@ window.addEventListener("load", function() {
|
||||
title: '请确认',
|
||||
text: '你是否要继续前往购买页面?请注意,你所购买的不是SaaS(软件即服务)订阅,而是一项自助托管解决方案的许可证。你需要将其部署在自己的服务器上。',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
}).then((result) => {
|
||||
@@ -849,7 +849,7 @@ window.addEventListener("load", function() {
|
||||
title: '请确认',
|
||||
text: '请注意,我们不提供退款。 我们强烈建议您在考虑购买专业版计划之前先测试我们的免费版本。 您还有兴趣继续吗?',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
showCancelButton: true, reverseButtons: true,
|
||||
confirmButtonText: '是',
|
||||
cancelButtonText: '否',
|
||||
}).then((result) => {
|
||||
|
||||
Reference in New Issue
Block a user