Clarify watermark features across packages
This commit is contained in:
@@ -2317,7 +2317,10 @@
|
|||||||
"event_checklist": "Event-Checkliste",
|
"event_checklist": "Event-Checkliste",
|
||||||
"advanced_analytics": "Erweiterte Statistiken",
|
"advanced_analytics": "Erweiterte Statistiken",
|
||||||
"branding_allowed": "Branding",
|
"branding_allowed": "Branding",
|
||||||
"watermark_allowed": "Wasserzeichen"
|
"watermark_allowed": "Wasserzeichen",
|
||||||
|
"watermark_base": "Fotospiel-Wasserzeichen",
|
||||||
|
"no_watermark": "Fotospiel-Wasserzeichen entfernen",
|
||||||
|
"watermark_custom": "Eigenes Wasserzeichen"
|
||||||
},
|
},
|
||||||
"hint": "Im Billing kannst du dein Paket jederzeit prüfen oder upgraden.",
|
"hint": "Im Billing kannst du dein Paket jederzeit prüfen oder upgraden.",
|
||||||
"continue": "Weiter zum Event-Setup",
|
"continue": "Weiter zum Event-Setup",
|
||||||
@@ -2910,7 +2913,10 @@
|
|||||||
"live_slideshow": "Live-Slideshow",
|
"live_slideshow": "Live-Slideshow",
|
||||||
"priority_support": "Priorisierter Support",
|
"priority_support": "Priorisierter Support",
|
||||||
"unlimited_sharing": "Unbegrenztes Teilen",
|
"unlimited_sharing": "Unbegrenztes Teilen",
|
||||||
"watermark_removal": "Kein Wasserzeichen"
|
"watermark_removal": "Kein Wasserzeichen",
|
||||||
|
"watermark_base": "Fotospiel-Wasserzeichen",
|
||||||
|
"no_watermark": "Fotospiel-Wasserzeichen entfernen",
|
||||||
|
"watermark_custom": "Eigenes Wasserzeichen"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"active": "Aktives Paket",
|
"active": "Aktives Paket",
|
||||||
|
|||||||
@@ -2319,7 +2319,10 @@
|
|||||||
"event_checklist": "Event checklist",
|
"event_checklist": "Event checklist",
|
||||||
"advanced_analytics": "Advanced analytics",
|
"advanced_analytics": "Advanced analytics",
|
||||||
"branding_allowed": "Branding",
|
"branding_allowed": "Branding",
|
||||||
"watermark_allowed": "Watermarks"
|
"watermark_allowed": "Watermarks",
|
||||||
|
"watermark_base": "Fotospiel watermark",
|
||||||
|
"no_watermark": "Remove Fotospiel watermark",
|
||||||
|
"watermark_custom": "Custom watermark"
|
||||||
},
|
},
|
||||||
"hint": "You can revisit billing any time to review or upgrade your package.",
|
"hint": "You can revisit billing any time to review or upgrade your package.",
|
||||||
"continue": "Continue to event setup",
|
"continue": "Continue to event setup",
|
||||||
@@ -2912,7 +2915,10 @@
|
|||||||
"live_slideshow": "Live slideshow",
|
"live_slideshow": "Live slideshow",
|
||||||
"priority_support": "Priority support",
|
"priority_support": "Priority support",
|
||||||
"unlimited_sharing": "Unlimited sharing",
|
"unlimited_sharing": "Unlimited sharing",
|
||||||
"watermark_removal": "No Watermark"
|
"watermark_removal": "No Watermark",
|
||||||
|
"watermark_base": "Fotospiel watermark",
|
||||||
|
"no_watermark": "Remove Fotospiel watermark",
|
||||||
|
"watermark_custom": "Custom watermark"
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"active": "Active Plan",
|
"active": "Active Plan",
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import {
|
|||||||
formatEventUsage,
|
formatEventUsage,
|
||||||
getPackageFeatureLabel,
|
getPackageFeatureLabel,
|
||||||
getPackageLimitEntries,
|
getPackageLimitEntries,
|
||||||
|
resolveTenantWatermarkFeatureKey,
|
||||||
} from './lib/packageSummary';
|
} from './lib/packageSummary';
|
||||||
import {
|
import {
|
||||||
PendingCheckout,
|
PendingCheckout,
|
||||||
@@ -564,7 +565,7 @@ function PackageCard({
|
|||||||
) : null}
|
) : null}
|
||||||
{isPartnerPackage && includedTierLabel ? <PillBadge tone="muted">{includedTierLabel}</PillBadge> : null}
|
{isPartnerPackage && includedTierLabel ? <PillBadge tone="muted">{includedTierLabel}</PillBadge> : null}
|
||||||
{!isPartnerPackage ? renderFeatureBadge(pkg, t, 'branding_allowed', t('billing.features.branding', 'Branding')) : null}
|
{!isPartnerPackage ? renderFeatureBadge(pkg, t, 'branding_allowed', t('billing.features.branding', 'Branding')) : null}
|
||||||
{!isPartnerPackage ? renderFeatureBadge(pkg, t, 'watermark_allowed', t('billing.features.watermark', 'Watermark')) : null}
|
{!isPartnerPackage ? renderWatermarkBadge(pkg, t) : null}
|
||||||
</XStack>
|
</XStack>
|
||||||
{eventUsageText ? (
|
{eventUsageText ? (
|
||||||
<Text fontSize="$xs" color={muted}>
|
<Text fontSize="$xs" color={muted}>
|
||||||
@@ -632,6 +633,16 @@ function renderFeatureBadge(pkg: TenantPackageSummary, t: any, key: string, labe
|
|||||||
return <PillBadge tone={enabled ? 'success' : 'muted'}>{enabled ? label : `${label} off`}</PillBadge>;
|
return <PillBadge tone={enabled ? 'success' : 'muted'}>{enabled ? label : `${label} off`}</PillBadge>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderWatermarkBadge(pkg: TenantPackageSummary, t: any) {
|
||||||
|
const featureKey = resolveTenantWatermarkFeatureKey(pkg);
|
||||||
|
if (!featureKey) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tone = featureKey === 'watermark_base' ? 'muted' : 'success';
|
||||||
|
return <PillBadge tone={tone}>{getPackageFeatureLabel(featureKey, t)}</PillBadge>;
|
||||||
|
}
|
||||||
|
|
||||||
function UsageBar({ metric }: { metric: PackageUsageMetric }) {
|
function UsageBar({ metric }: { metric: PackageUsageMetric }) {
|
||||||
const { t } = useTranslation('management');
|
const { t } = useTranslation('management');
|
||||||
const { muted, textStrong, border, primary, subtle, warningText, danger } = useAdminTheme();
|
const { muted, textStrong, border, primary, subtle, warningText, danger } = useAdminTheme();
|
||||||
|
|||||||
@@ -60,19 +60,21 @@ describe('selectRecommendedPackageId', () => {
|
|||||||
it('selects the cheapest package with watermark access when requested', () => {
|
it('selects the cheapest package with watermark access when requested', () => {
|
||||||
const watermarkPackages = [
|
const watermarkPackages = [
|
||||||
{ id: 1, price: 100, watermark_allowed: false, features: {} },
|
{ id: 1, price: 100, watermark_allowed: false, features: {} },
|
||||||
{ id: 2, price: 120, watermark_allowed: true, features: {} },
|
{ id: 2, price: 120, watermark_allowed: true, features: { no_watermark: true } },
|
||||||
{ id: 3, price: 180, watermark_allowed: true, features: {} },
|
{ id: 3, price: 180, watermark_allowed: true, features: {} },
|
||||||
] as any;
|
] as any;
|
||||||
const active = { id: 1, price: 100, watermark_allowed: false, features: {} } as any;
|
const active = { id: 1, price: 100, watermark_allowed: false, features: {} } as any;
|
||||||
expect(selectRecommendedPackageId(watermarkPackages, 'watermark_allowed', active)).toBe(2);
|
expect(selectRecommendedPackageId(watermarkPackages, 'watermark_allowed', active)).toBe(2);
|
||||||
|
expect(selectRecommendedPackageId(watermarkPackages, 'no_watermark', active)).toBe(2);
|
||||||
|
expect(selectRecommendedPackageId(watermarkPackages, 'watermark_custom', active)).toBe(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('buildPackageComparisonRows', () => {
|
describe('buildPackageComparisonRows', () => {
|
||||||
it('includes limit rows and enabled feature rows', () => {
|
it('includes limit rows and enabled feature rows', () => {
|
||||||
const rows = buildPackageComparisonRows([
|
const rows = buildPackageComparisonRows([
|
||||||
{ features: { advanced_analytics: true, custom_branding: false } },
|
{ features: { advanced_analytics: true, custom_branding: false }, watermark_allowed: false },
|
||||||
{ features: { custom_branding: true, watermark_removal: true } },
|
{ features: { custom_branding: true, no_watermark: true }, watermark_allowed: true },
|
||||||
] as any);
|
] as any);
|
||||||
|
|
||||||
expect(rows.map((row) => row.id)).toEqual([
|
expect(rows.map((row) => row.id)).toEqual([
|
||||||
@@ -81,7 +83,8 @@ describe('buildPackageComparisonRows', () => {
|
|||||||
'limit.gallery_days',
|
'limit.gallery_days',
|
||||||
'feature.advanced_analytics',
|
'feature.advanced_analytics',
|
||||||
'feature.custom_branding',
|
'feature.custom_branding',
|
||||||
'feature.watermark_removal',
|
'feature.no_watermark',
|
||||||
|
'feature.watermark_base',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -90,4 +93,13 @@ describe('getEnabledPackageFeatures', () => {
|
|||||||
it('accepts array payloads', () => {
|
it('accepts array payloads', () => {
|
||||||
expect(getEnabledPackageFeatures({ features: ['custom_branding', ''] } as any)).toEqual(['custom_branding']);
|
expect(getEnabledPackageFeatures({ features: ['custom_branding', ''] } as any)).toEqual(['custom_branding']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('adds watermark feature for endcustomer packages', () => {
|
||||||
|
expect(
|
||||||
|
getEnabledPackageFeatures({ watermark_allowed: false, features: [] } as any)
|
||||||
|
).toEqual(['watermark_base']);
|
||||||
|
expect(
|
||||||
|
getEnabledPackageFeatures({ watermark_allowed: true, features: ['no_watermark'] } as any)
|
||||||
|
).toEqual(['no_watermark']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,11 +41,26 @@ function normalizePackageFeatures(pkg: Package | null): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getEnabledPackageFeatures(pkg: Package): string[] {
|
export function getEnabledPackageFeatures(pkg: Package): string[] {
|
||||||
return normalizePackageFeatures(pkg);
|
const features = normalizePackageFeatures(pkg);
|
||||||
|
const watermarkFeature = resolvePackageWatermarkFeatureKey(pkg, features);
|
||||||
|
|
||||||
|
if (watermarkFeature) {
|
||||||
|
const cleaned = features.filter(
|
||||||
|
(feature) => !['watermark', 'watermark_allowed', 'no_watermark', 'watermark_base', 'watermark_custom'].includes(feature)
|
||||||
|
);
|
||||||
|
cleaned.push(watermarkFeature);
|
||||||
|
return Array.from(new Set(cleaned));
|
||||||
|
}
|
||||||
|
|
||||||
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectFeatures(pkg: Package | null): Set<string> {
|
function collectFeatures(pkg: Package | null): Set<string> {
|
||||||
return new Set(normalizePackageFeatures(pkg));
|
if (!pkg) {
|
||||||
|
return new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Set(getEnabledPackageFeatures(pkg));
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareLimit(candidate: number | null, active: number | null): number {
|
function compareLimit(candidate: number | null, active: number | null): number {
|
||||||
@@ -119,9 +134,12 @@ export function selectRecommendedPackageId(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const candidates = feature === 'watermark_allowed'
|
const candidates =
|
||||||
? packages.filter((pkg) => pkg.watermark_allowed === true)
|
feature === 'watermark_allowed'
|
||||||
: packages.filter((pkg) => normalizePackageFeatures(pkg).includes(feature));
|
? packages.filter((pkg) => pkg.watermark_allowed === true)
|
||||||
|
: feature?.startsWith('watermark')
|
||||||
|
? packages.filter((pkg) => resolvePackageWatermarkFeatureKey(pkg, normalizePackageFeatures(pkg)) === feature)
|
||||||
|
: packages.filter((pkg) => normalizePackageFeatures(pkg).includes(feature));
|
||||||
if (candidates.length === 0) {
|
if (candidates.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -151,7 +169,7 @@ export function buildPackageComparisonRows(packages: Package[]): PackageComparis
|
|||||||
|
|
||||||
const featureKeys = new Set<string>();
|
const featureKeys = new Set<string>();
|
||||||
packages.forEach((pkg) => {
|
packages.forEach((pkg) => {
|
||||||
normalizePackageFeatures(pkg).forEach((key) => {
|
getEnabledPackageFeatures(pkg).forEach((key) => {
|
||||||
if (key !== 'photos') {
|
if (key !== 'photos') {
|
||||||
featureKeys.add(key);
|
featureKeys.add(key);
|
||||||
}
|
}
|
||||||
@@ -168,3 +186,23 @@ export function buildPackageComparisonRows(packages: Package[]): PackageComparis
|
|||||||
|
|
||||||
return [...limitRows, ...featureRows];
|
return [...limitRows, ...featureRows];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolvePackageWatermarkFeatureKey(pkg: Package, features: string[]): string | null {
|
||||||
|
if (pkg.type === 'reseller') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkg.watermark_allowed === false) {
|
||||||
|
return 'watermark_base';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (features.includes('no_watermark')) {
|
||||||
|
return 'no_watermark';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkg.watermark_allowed === true) {
|
||||||
|
return 'watermark_custom';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ describe('packageSummary helpers', () => {
|
|||||||
watermark_allowed: false,
|
watermark_allowed: false,
|
||||||
} as any);
|
} as any);
|
||||||
|
|
||||||
expect(result).toEqual(expect.arrayContaining(['custom_branding', 'reseller_dashboard', 'branding_allowed']));
|
expect(result).toEqual(
|
||||||
|
expect.arrayContaining(['custom_branding', 'reseller_dashboard', 'branding_allowed', 'watermark_base'])
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns labeled limit entries', () => {
|
it('returns labeled limit entries', () => {
|
||||||
|
|||||||
@@ -80,6 +80,18 @@ const FEATURE_LABELS: Record<string, { key: string; fallback: string }> = {
|
|||||||
key: 'mobileDashboard.packageSummary.feature.watermark_allowed',
|
key: 'mobileDashboard.packageSummary.feature.watermark_allowed',
|
||||||
fallback: 'Watermarks',
|
fallback: 'Watermarks',
|
||||||
},
|
},
|
||||||
|
watermark_base: {
|
||||||
|
key: 'mobileDashboard.packageSummary.feature.watermark_base',
|
||||||
|
fallback: 'Fotospiel watermark',
|
||||||
|
},
|
||||||
|
no_watermark: {
|
||||||
|
key: 'mobileDashboard.packageSummary.feature.no_watermark',
|
||||||
|
fallback: 'Remove Fotospiel watermark',
|
||||||
|
},
|
||||||
|
watermark_custom: {
|
||||||
|
key: 'mobileDashboard.packageSummary.feature.watermark_custom',
|
||||||
|
fallback: 'Custom watermark',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const LIMIT_LABELS: Array<{ key: string; labelKey: string; fallback: string }> = [
|
const LIMIT_LABELS: Array<{ key: string; labelKey: string; fallback: string }> = [
|
||||||
@@ -241,13 +253,38 @@ export function collectPackageFeatures(pkg: TenantPackageSummary): string[] {
|
|||||||
features.add('branding_allowed');
|
features.add('branding_allowed');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkg.package_type !== 'reseller' && pkg.watermark_allowed) {
|
const watermarkFeature = resolveTenantWatermarkFeatureKey(pkg);
|
||||||
features.add('watermark_allowed');
|
if (watermarkFeature) {
|
||||||
|
['watermark_allowed', 'watermark', 'no_watermark', 'watermark_base', 'watermark_custom'].forEach((key) =>
|
||||||
|
features.delete(key)
|
||||||
|
);
|
||||||
|
features.add(watermarkFeature);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.from(features);
|
return Array.from(features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveTenantWatermarkFeatureKey(pkg: TenantPackageSummary): string | null {
|
||||||
|
if (pkg.package_type === 'reseller') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkg.watermark_allowed === false) {
|
||||||
|
return 'watermark_base';
|
||||||
|
}
|
||||||
|
|
||||||
|
const features = Array.isArray(pkg.features) ? pkg.features : [];
|
||||||
|
if (features.includes('no_watermark')) {
|
||||||
|
return 'no_watermark';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkg.watermark_allowed === true) {
|
||||||
|
return 'watermark_custom';
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export function formatEventUsage(used: number | null, limit: number | null, t: Translate): string | null {
|
export function formatEventUsage(used: number | null, limit: number | null, t: Translate): string | null {
|
||||||
if (limit === null || used === null) {
|
if (limit === null || used === null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -54,7 +54,17 @@ export const resolveWatermarkFeatureKey = (pkg: Package): string => {
|
|||||||
return 'watermark_custom';
|
return 'watermark_custom';
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkg.watermark_allowed === false ? 'no_watermark' : 'watermark';
|
const features = Array.isArray(pkg.features) ? pkg.features : [];
|
||||||
|
|
||||||
|
if (pkg.watermark_allowed === false) {
|
||||||
|
return 'watermark_base';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (features.includes('no_watermark')) {
|
||||||
|
return 'no_watermark';
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkg.watermark_allowed === true ? 'watermark_custom' : 'watermark';
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortPackagesByPrice = (packages: Package[]): Package[] =>
|
const sortPackagesByPrice = (packages: Package[]): Package[] =>
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ describe('resolveWatermarkFeatureKey', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('falls back to watermark_allowed when slug is unknown', () => {
|
it('falls back to watermark_allowed when slug is unknown', () => {
|
||||||
expect(resolveWatermarkFeatureKey({ slug: 'reseller', watermark_allowed: true } as any)).toBe('watermark');
|
expect(resolveWatermarkFeatureKey({ slug: 'reseller', watermark_allowed: true } as any)).toBe('watermark_custom');
|
||||||
expect(resolveWatermarkFeatureKey({ slug: 'reseller', watermark_allowed: false } as any)).toBe('no_watermark');
|
expect(resolveWatermarkFeatureKey({ slug: 'reseller', watermark_allowed: false } as any)).toBe('watermark_base');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prefers explicit no_watermark features for unknown slugs', () => {
|
||||||
|
expect(
|
||||||
|
resolveWatermarkFeatureKey({ slug: 'reseller', watermark_allowed: true, features: ['no_watermark'] } as any)
|
||||||
|
).toBe('no_watermark');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -89,13 +89,13 @@
|
|||||||
"feature_live_slideshow": "Live-Slideshow",
|
"feature_live_slideshow": "Live-Slideshow",
|
||||||
"feature_analytics": "Analytics",
|
"feature_analytics": "Analytics",
|
||||||
"feature_watermark": "Wasserzeichen",
|
"feature_watermark": "Wasserzeichen",
|
||||||
"feature_watermark_base": "Unser Wasserzeichen",
|
"feature_watermark_base": "Fotospiel-Wasserzeichen aktiv",
|
||||||
"feature_watermark_custom": "Eigenes Wasserzeichen",
|
"feature_watermark_custom": "Eigenes Wasserzeichen",
|
||||||
"feature_branding": "Branding",
|
"feature_branding": "Branding",
|
||||||
"feature_support": "Support",
|
"feature_support": "Support",
|
||||||
"feature_basic_uploads": "Basis-Uploads",
|
"feature_basic_uploads": "Basis-Uploads",
|
||||||
"feature_unlimited_sharing": "Unbegrenztes Teilen",
|
"feature_unlimited_sharing": "Unbegrenztes Teilen",
|
||||||
"feature_no_watermark": "Kein Wasserzeichen",
|
"feature_no_watermark": "Fotospiel-Wasserzeichen entfernen",
|
||||||
"feature_custom_tasks": "Benutzerdefinierte Tasks",
|
"feature_custom_tasks": "Benutzerdefinierte Tasks",
|
||||||
"feature_advanced_analytics": "Erweiterte Analytics",
|
"feature_advanced_analytics": "Erweiterte Analytics",
|
||||||
"feature_priority_support": "Priorisierter Support",
|
"feature_priority_support": "Priorisierter Support",
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ return [
|
|||||||
'feature_live_slideshow' => 'Live-Slideshow',
|
'feature_live_slideshow' => 'Live-Slideshow',
|
||||||
'feature_analytics' => 'Analytics',
|
'feature_analytics' => 'Analytics',
|
||||||
'feature_watermark' => 'Wasserzeichen',
|
'feature_watermark' => 'Wasserzeichen',
|
||||||
'feature_watermark_base' => 'Unser Wasserzeichen',
|
'feature_watermark_base' => 'Fotospiel-Wasserzeichen aktiv',
|
||||||
'feature_watermark_custom' => 'Eigenes Wasserzeichen',
|
'feature_watermark_custom' => 'Eigenes Wasserzeichen',
|
||||||
'feature_branding' => 'Branding',
|
'feature_branding' => 'Branding',
|
||||||
'feature_support' => 'Support',
|
'feature_support' => 'Support',
|
||||||
'feature_basic_uploads' => 'Grundlegende Uploads',
|
'feature_basic_uploads' => 'Grundlegende Uploads',
|
||||||
'feature_unlimited_sharing' => 'Unbegrenztes Teilen',
|
'feature_unlimited_sharing' => 'Unbegrenztes Teilen',
|
||||||
'feature_no_watermark' => 'Kein Wasserzeichen',
|
'feature_no_watermark' => 'Fotospiel-Wasserzeichen entfernen',
|
||||||
'feature_custom_tasks' => 'Benutzerdefinierte Tasks',
|
'feature_custom_tasks' => 'Benutzerdefinierte Tasks',
|
||||||
'feature_advanced_analytics' => 'Erweiterte Analytics',
|
'feature_advanced_analytics' => 'Erweiterte Analytics',
|
||||||
'feature_priority_support' => 'Priorisierter Support',
|
'feature_priority_support' => 'Priorisierter Support',
|
||||||
|
|||||||
@@ -89,13 +89,13 @@
|
|||||||
"feature_live_slideshow": "Live Slideshow",
|
"feature_live_slideshow": "Live Slideshow",
|
||||||
"feature_analytics": "Analytics",
|
"feature_analytics": "Analytics",
|
||||||
"feature_watermark": "Watermark",
|
"feature_watermark": "Watermark",
|
||||||
"feature_watermark_base": "Our watermark",
|
"feature_watermark_base": "Fotospiel watermark applied",
|
||||||
"feature_watermark_custom": "Custom watermark",
|
"feature_watermark_custom": "Custom watermark",
|
||||||
"feature_branding": "Branding",
|
"feature_branding": "Branding",
|
||||||
"feature_support": "Support",
|
"feature_support": "Support",
|
||||||
"feature_basic_uploads": "Basic Uploads",
|
"feature_basic_uploads": "Basic Uploads",
|
||||||
"feature_unlimited_sharing": "Unlimited Sharing",
|
"feature_unlimited_sharing": "Unlimited Sharing",
|
||||||
"feature_no_watermark": "No Watermark",
|
"feature_no_watermark": "Remove Fotospiel watermark",
|
||||||
"feature_custom_tasks": "Custom Tasks",
|
"feature_custom_tasks": "Custom Tasks",
|
||||||
"feature_advanced_analytics": "Advanced Analytics",
|
"feature_advanced_analytics": "Advanced Analytics",
|
||||||
"feature_priority_support": "Priority Support",
|
"feature_priority_support": "Priority Support",
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ return [
|
|||||||
'feature_live_slideshow' => 'Live Slideshow',
|
'feature_live_slideshow' => 'Live Slideshow',
|
||||||
'feature_analytics' => 'Analytics',
|
'feature_analytics' => 'Analytics',
|
||||||
'feature_watermark' => 'Watermark',
|
'feature_watermark' => 'Watermark',
|
||||||
'feature_watermark_base' => 'Our watermark',
|
'feature_watermark_base' => 'Fotospiel watermark applied',
|
||||||
'feature_watermark_custom' => 'Custom watermark',
|
'feature_watermark_custom' => 'Custom watermark',
|
||||||
'feature_branding' => 'Branding',
|
'feature_branding' => 'Branding',
|
||||||
'feature_support' => 'Support',
|
'feature_support' => 'Support',
|
||||||
'feature_basic_uploads' => 'Basic Uploads',
|
'feature_basic_uploads' => 'Basic Uploads',
|
||||||
'feature_unlimited_sharing' => 'Unlimited Sharing',
|
'feature_unlimited_sharing' => 'Unlimited Sharing',
|
||||||
'feature_no_watermark' => 'No Watermark',
|
'feature_no_watermark' => 'Remove Fotospiel watermark',
|
||||||
'feature_custom_tasks' => 'Custom Tasks',
|
'feature_custom_tasks' => 'Custom Tasks',
|
||||||
'feature_advanced_analytics' => 'Advanced Analytics',
|
'feature_advanced_analytics' => 'Advanced Analytics',
|
||||||
'feature_priority_support' => 'Priority Support',
|
'feature_priority_support' => 'Priority Support',
|
||||||
|
|||||||
Reference in New Issue
Block a user