feat(api): add SEK, DKK and NOK as localized currencies (#2684)

This commit is contained in:
Hampus
2026-09-11 15:48:56 +02:00
committed by GitHub
parent 0e470f532e
commit 3af43b3366
50 changed files with 668 additions and 390 deletions
+12
View File
@@ -372,17 +372,29 @@ export function buildAPIConfigFromMaster(master: MasterConfig): APIConfig {
monthlyUsd: master.integrations.stripe.prices.monthly_usd, monthlyUsd: master.integrations.stripe.prices.monthly_usd,
monthlyEur: master.integrations.stripe.prices.monthly_eur, monthlyEur: master.integrations.stripe.prices.monthly_eur,
monthlyBrl: master.integrations.stripe.prices.monthly_brl, monthlyBrl: master.integrations.stripe.prices.monthly_brl,
monthlyDkk: master.integrations.stripe.prices.monthly_dkk,
monthlyInr: master.integrations.stripe.prices.monthly_inr, monthlyInr: master.integrations.stripe.prices.monthly_inr,
monthlyNok: master.integrations.stripe.prices.monthly_nok,
monthlyPln: master.integrations.stripe.prices.monthly_pln, monthlyPln: master.integrations.stripe.prices.monthly_pln,
monthlySek: master.integrations.stripe.prices.monthly_sek,
monthlyTry: master.integrations.stripe.prices.monthly_try, monthlyTry: master.integrations.stripe.prices.monthly_try,
yearlyUsd: master.integrations.stripe.prices.yearly_usd, yearlyUsd: master.integrations.stripe.prices.yearly_usd,
yearlyEur: master.integrations.stripe.prices.yearly_eur, yearlyEur: master.integrations.stripe.prices.yearly_eur,
yearlyBrl: master.integrations.stripe.prices.yearly_brl, yearlyBrl: master.integrations.stripe.prices.yearly_brl,
yearlyDkk: master.integrations.stripe.prices.yearly_dkk,
yearlyInr: master.integrations.stripe.prices.yearly_inr, yearlyInr: master.integrations.stripe.prices.yearly_inr,
yearlyNok: master.integrations.stripe.prices.yearly_nok,
yearlyPln: master.integrations.stripe.prices.yearly_pln, yearlyPln: master.integrations.stripe.prices.yearly_pln,
yearlySek: master.integrations.stripe.prices.yearly_sek,
yearlyTry: master.integrations.stripe.prices.yearly_try, yearlyTry: master.integrations.stripe.prices.yearly_try,
gift1MonthUsd: master.integrations.stripe.prices.gift_1_month_usd, gift1MonthUsd: master.integrations.stripe.prices.gift_1_month_usd,
gift1MonthEur: master.integrations.stripe.prices.gift_1_month_eur, gift1MonthEur: master.integrations.stripe.prices.gift_1_month_eur,
gift1MonthSek: master.integrations.stripe.prices.gift_1_month_sek,
gift1YearSek: master.integrations.stripe.prices.gift_1_year_sek,
gift1MonthDkk: master.integrations.stripe.prices.gift_1_month_dkk,
gift1YearDkk: master.integrations.stripe.prices.gift_1_year_dkk,
gift1MonthNok: master.integrations.stripe.prices.gift_1_month_nok,
gift1YearNok: master.integrations.stripe.prices.gift_1_year_nok,
gift1MonthBrl: master.integrations.stripe.prices.gift_1_month_brl, gift1MonthBrl: master.integrations.stripe.prices.gift_1_month_brl,
gift1MonthInr: master.integrations.stripe.prices.gift_1_month_inr, gift1MonthInr: master.integrations.stripe.prices.gift_1_month_inr,
gift1MonthPln: master.integrations.stripe.prices.gift_1_month_pln, gift1MonthPln: master.integrations.stripe.prices.gift_1_month_pln,
+12
View File
@@ -226,17 +226,29 @@ export interface APIConfig {
monthlyUsd?: string; monthlyUsd?: string;
monthlyEur?: string; monthlyEur?: string;
monthlyBrl?: string; monthlyBrl?: string;
monthlyDkk?: string;
monthlyInr?: string; monthlyInr?: string;
monthlyNok?: string;
monthlyPln?: string; monthlyPln?: string;
monthlySek?: string;
monthlyTry?: string; monthlyTry?: string;
yearlyUsd?: string; yearlyUsd?: string;
yearlyEur?: string; yearlyEur?: string;
yearlyBrl?: string; yearlyBrl?: string;
yearlyDkk?: string;
yearlyInr?: string; yearlyInr?: string;
yearlyNok?: string;
yearlyPln?: string; yearlyPln?: string;
yearlySek?: string;
yearlyTry?: string; yearlyTry?: string;
gift1MonthUsd?: string; gift1MonthUsd?: string;
gift1MonthEur?: string; gift1MonthEur?: string;
gift1MonthSek?: string;
gift1YearSek?: string;
gift1MonthDkk?: string;
gift1YearDkk?: string;
gift1MonthNok?: string;
gift1YearNok?: string;
gift1MonthBrl?: string; gift1MonthBrl?: string;
gift1MonthInr?: string; gift1MonthInr?: string;
gift1MonthPln?: string; gift1MonthPln?: string;
+14 -14
View File
@@ -32064,9 +32064,9 @@
"description": "The amount the user is actually charged, in the currency minor unit" "description": "The amount the user is actually charged, in the currency minor unit"
}, },
"currency": { "currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"description": "Currency of the charged amount" "description": "Currency of the charged amount"
}, },
"billing_cycle": { "billing_cycle": {
@@ -32345,9 +32345,9 @@
"currency": { "currency": {
"anyOf": [ "anyOf": [
{ {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"] "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"]
}, },
{"type": "null"} {"type": "null"}
], ],
@@ -32418,9 +32418,9 @@
"currency": { "currency": {
"anyOf": [ "anyOf": [
{ {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"] "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"]
}, },
{"type": "null"} {"type": "null"}
], ],
@@ -32662,15 +32662,15 @@
"description": "Gift 1 year price amount in the currency minor unit" "description": "Gift 1 year price amount in the currency minor unit"
}, },
"currency": { "currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"description": "Currency for the prices" "description": "Currency for the prices"
}, },
"gift_currency": { "gift_currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"description": "Currency for gift prices" "description": "Currency for gift prices"
} }
}, },
@@ -32749,9 +32749,9 @@
"description": "Amount billed before the switch, in the currency minor unit" "description": "Amount billed before the switch, in the currency minor unit"
}, },
"currency": { "currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"description": "Currency of both amounts" "description": "Currency of both amounts"
} }
}, },
@@ -32788,9 +32788,9 @@
"description": "Amount billed before the switch, in the currency minor unit" "description": "Amount billed before the switch, in the currency minor unit"
}, },
"currency": { "currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string", "type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"], "x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"description": "Currency of both amounts" "description": "Currency of both amounts"
} }
}, },
@@ -56,8 +56,11 @@ const LEGACY_SLOT_CURRENCIES: Record<string, Currency | undefined> = {
usd: 'USD', usd: 'USD',
eur: 'EUR', eur: 'EUR',
brl: 'BRL', brl: 'BRL',
dkk: 'DKK',
inr: 'INR', inr: 'INR',
nok: 'NOK',
pln: 'PLN', pln: 'PLN',
sek: 'SEK',
try: 'TRY', try: 'TRY',
}; };
@@ -109,6 +112,14 @@ export class ProductRegistry {
currency: 'BRL', currency: 'BRL',
billingCycle: 'monthly', billingCycle: 'monthly',
}); });
this.registerProduct(prices.monthlyDkk, {
type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 1,
isGift: false,
currency: 'DKK',
billingCycle: 'monthly',
});
this.registerProduct(prices.monthlyInr, { this.registerProduct(prices.monthlyInr, {
type: ProductType.MONTHLY_SUBSCRIPTION, type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -117,6 +128,14 @@ export class ProductRegistry {
currency: 'INR', currency: 'INR',
billingCycle: 'monthly', billingCycle: 'monthly',
}); });
this.registerProduct(prices.monthlyNok, {
type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 1,
isGift: false,
currency: 'NOK',
billingCycle: 'monthly',
});
this.registerProduct(prices.monthlyPln, { this.registerProduct(prices.monthlyPln, {
type: ProductType.MONTHLY_SUBSCRIPTION, type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -125,6 +144,14 @@ export class ProductRegistry {
currency: 'PLN', currency: 'PLN',
billingCycle: 'monthly', billingCycle: 'monthly',
}); });
this.registerProduct(prices.monthlySek, {
type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 1,
isGift: false,
currency: 'SEK',
billingCycle: 'monthly',
});
this.registerProduct(prices.monthlyTry, { this.registerProduct(prices.monthlyTry, {
type: ProductType.MONTHLY_SUBSCRIPTION, type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -157,6 +184,14 @@ export class ProductRegistry {
currency: 'BRL', currency: 'BRL',
billingCycle: 'yearly', billingCycle: 'yearly',
}); });
this.registerProduct(prices.yearlyDkk, {
type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 12,
isGift: false,
currency: 'DKK',
billingCycle: 'yearly',
});
this.registerProduct(prices.yearlyInr, { this.registerProduct(prices.yearlyInr, {
type: ProductType.YEARLY_SUBSCRIPTION, type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -165,6 +200,14 @@ export class ProductRegistry {
currency: 'INR', currency: 'INR',
billingCycle: 'yearly', billingCycle: 'yearly',
}); });
this.registerProduct(prices.yearlyNok, {
type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 12,
isGift: false,
currency: 'NOK',
billingCycle: 'yearly',
});
this.registerProduct(prices.yearlyPln, { this.registerProduct(prices.yearlyPln, {
type: ProductType.YEARLY_SUBSCRIPTION, type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -173,6 +216,14 @@ export class ProductRegistry {
currency: 'PLN', currency: 'PLN',
billingCycle: 'yearly', billingCycle: 'yearly',
}); });
this.registerProduct(prices.yearlySek, {
type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 12,
isGift: false,
currency: 'SEK',
billingCycle: 'yearly',
});
this.registerProduct(prices.yearlyTry, { this.registerProduct(prices.yearlyTry, {
type: ProductType.YEARLY_SUBSCRIPTION, type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -209,6 +260,48 @@ export class ProductRegistry {
isGift: true, isGift: true,
currency: 'INR', currency: 'INR',
}); });
this.registerProduct(prices.gift1MonthDkk, {
type: ProductType.GIFT_1_MONTH,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 1,
isGift: true,
currency: 'DKK',
});
this.registerProduct(prices.gift1YearDkk, {
type: ProductType.GIFT_1_YEAR,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 12,
isGift: true,
currency: 'DKK',
});
this.registerProduct(prices.gift1MonthNok, {
type: ProductType.GIFT_1_MONTH,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 1,
isGift: true,
currency: 'NOK',
});
this.registerProduct(prices.gift1YearNok, {
type: ProductType.GIFT_1_YEAR,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 12,
isGift: true,
currency: 'NOK',
});
this.registerProduct(prices.gift1MonthSek, {
type: ProductType.GIFT_1_MONTH,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 1,
isGift: true,
currency: 'SEK',
});
this.registerProduct(prices.gift1YearSek, {
type: ProductType.GIFT_1_YEAR,
premiumType: UserPremiumTypes.SUBSCRIPTION,
durationMonths: 12,
isGift: true,
currency: 'SEK',
});
this.registerProduct(prices.gift1MonthPln, { this.registerProduct(prices.gift1MonthPln, {
type: ProductType.GIFT_1_MONTH, type: ProductType.GIFT_1_MONTH,
premiumType: UserPremiumTypes.SUBSCRIPTION, premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -319,12 +412,21 @@ export class ProductRegistry {
if (normalizedCurrency === 'brl') { if (normalizedCurrency === 'brl') {
return billingCycle === 'monthly' ? (prices.monthlyBrl ?? null) : (prices.yearlyBrl ?? null); return billingCycle === 'monthly' ? (prices.monthlyBrl ?? null) : (prices.yearlyBrl ?? null);
} }
if (normalizedCurrency === 'dkk') {
return billingCycle === 'monthly' ? (prices.monthlyDkk ?? null) : (prices.yearlyDkk ?? null);
}
if (normalizedCurrency === 'inr') { if (normalizedCurrency === 'inr') {
return billingCycle === 'monthly' ? (prices.monthlyInr ?? null) : (prices.yearlyInr ?? null); return billingCycle === 'monthly' ? (prices.monthlyInr ?? null) : (prices.yearlyInr ?? null);
} }
if (normalizedCurrency === 'nok') {
return billingCycle === 'monthly' ? (prices.monthlyNok ?? null) : (prices.yearlyNok ?? null);
}
if (normalizedCurrency === 'pln') { if (normalizedCurrency === 'pln') {
return billingCycle === 'monthly' ? (prices.monthlyPln ?? null) : (prices.yearlyPln ?? null); return billingCycle === 'monthly' ? (prices.monthlyPln ?? null) : (prices.yearlyPln ?? null);
} }
if (normalizedCurrency === 'sek') {
return billingCycle === 'monthly' ? (prices.monthlySek ?? null) : (prices.yearlySek ?? null);
}
if (normalizedCurrency === 'try') { if (normalizedCurrency === 'try') {
return billingCycle === 'monthly' ? (prices.monthlyTry ?? null) : (prices.yearlyTry ?? null); return billingCycle === 'monthly' ? (prices.monthlyTry ?? null) : (prices.yearlyTry ?? null);
} }
@@ -349,6 +451,15 @@ export class ProductRegistry {
if (normalizedCurrency === 'inr') { if (normalizedCurrency === 'inr') {
return duration === 'gift_1_month' ? (prices.gift1MonthInr ?? null) : (prices.gift1YearInr ?? null); return duration === 'gift_1_month' ? (prices.gift1MonthInr ?? null) : (prices.gift1YearInr ?? null);
} }
if (normalizedCurrency === 'dkk') {
return duration === 'gift_1_month' ? (prices.gift1MonthDkk ?? null) : (prices.gift1YearDkk ?? null);
}
if (normalizedCurrency === 'nok') {
return duration === 'gift_1_month' ? (prices.gift1MonthNok ?? null) : (prices.gift1YearNok ?? null);
}
if (normalizedCurrency === 'sek') {
return duration === 'gift_1_month' ? (prices.gift1MonthSek ?? null) : (prices.gift1YearSek ?? null);
}
if (normalizedCurrency === 'pln') { if (normalizedCurrency === 'pln') {
return duration === 'gift_1_month' ? (prices.gift1MonthPln ?? null) : (prices.gift1YearPln ?? null); return duration === 'gift_1_month' ? (prices.gift1MonthPln ?? null) : (prices.gift1YearPln ?? null);
} }
@@ -104,8 +104,11 @@ function normalizeCurrency(value: string | null | undefined): Currency | null {
currency === 'USD' || currency === 'USD' ||
currency === 'EUR' || currency === 'EUR' ||
currency === 'BRL' || currency === 'BRL' ||
currency === 'DKK' ||
currency === 'INR' || currency === 'INR' ||
currency === 'NOK' ||
currency === 'PLN' || currency === 'PLN' ||
currency === 'SEK' ||
currency === 'TRY' currency === 'TRY'
) { ) {
return currency; return currency;
@@ -1108,6 +1108,15 @@ export class StripeCheckoutService {
yearly: prices.yearlyBrl, yearly: prices.yearlyBrl,
currency, currency,
}; };
case 'DKK':
if (!prices.monthlyDkk || !prices.yearlyDkk) {
return null;
}
return {
monthly: prices.monthlyDkk,
yearly: prices.yearlyDkk,
currency,
};
case 'INR': case 'INR':
if (!prices.monthlyInr || !prices.yearlyInr) { if (!prices.monthlyInr || !prices.yearlyInr) {
return null; return null;
@@ -1117,6 +1126,15 @@ export class StripeCheckoutService {
yearly: prices.yearlyInr, yearly: prices.yearlyInr,
currency, currency,
}; };
case 'NOK':
if (!prices.monthlyNok || !prices.yearlyNok) {
return null;
}
return {
monthly: prices.monthlyNok,
yearly: prices.yearlyNok,
currency,
};
case 'PLN': case 'PLN':
if (!prices.monthlyPln || !prices.yearlyPln) { if (!prices.monthlyPln || !prices.yearlyPln) {
return null; return null;
@@ -1126,6 +1144,15 @@ export class StripeCheckoutService {
yearly: prices.yearlyPln, yearly: prices.yearlyPln,
currency, currency,
}; };
case 'SEK':
if (!prices.monthlySek || !prices.yearlySek) {
return null;
}
return {
monthly: prices.monthlySek,
yearly: prices.yearlySek,
currency,
};
case 'TRY': case 'TRY':
if (!prices.monthlyTry || !prices.yearlyTry) { if (!prices.monthlyTry || !prices.yearlyTry) {
return null; return null;
@@ -1175,6 +1202,33 @@ export class StripeCheckoutService {
gift_1_year: prices.gift1YearInr, gift_1_year: prices.gift1YearInr,
gift_currency: 'INR', gift_currency: 'INR',
}; };
case 'DKK':
if (!prices.gift1MonthDkk || !prices.gift1YearDkk) {
return null;
}
return {
gift_1_month: prices.gift1MonthDkk,
gift_1_year: prices.gift1YearDkk,
gift_currency: 'DKK',
};
case 'NOK':
if (!prices.gift1MonthNok || !prices.gift1YearNok) {
return null;
}
return {
gift_1_month: prices.gift1MonthNok,
gift_1_year: prices.gift1YearNok,
gift_currency: 'NOK',
};
case 'SEK':
if (!prices.gift1MonthSek || !prices.gift1YearSek) {
return null;
}
return {
gift_1_month: prices.gift1MonthSek,
gift_1_year: prices.gift1YearSek,
gift_currency: 'SEK',
};
case 'PLN': case 'PLN':
if (!prices.gift1MonthPln || !prices.gift1YearPln) { if (!prices.gift1MonthPln || !prices.gift1YearPln) {
return null; return null;
@@ -119,16 +119,22 @@ describe('ProductRegistry - legacy prices', () => {
monthly_usd: ['legacy_usd'], monthly_usd: ['legacy_usd'],
monthly_eur: ['legacy_eur'], monthly_eur: ['legacy_eur'],
monthly_brl: ['legacy_brl'], monthly_brl: ['legacy_brl'],
monthly_dkk: ['legacy_dkk'],
monthly_inr: ['legacy_inr'], monthly_inr: ['legacy_inr'],
monthly_nok: ['legacy_nok'],
monthly_pln: ['legacy_pln'], monthly_pln: ['legacy_pln'],
monthly_sek: ['legacy_sek'],
monthly_try: ['legacy_try'], monthly_try: ['legacy_try'],
}, },
); );
expect(registry.getProduct('legacy_usd')?.currency).toBe('USD'); expect(registry.getProduct('legacy_usd')?.currency).toBe('USD');
expect(registry.getProduct('legacy_eur')?.currency).toBe('EUR'); expect(registry.getProduct('legacy_eur')?.currency).toBe('EUR');
expect(registry.getProduct('legacy_brl')?.currency).toBe('BRL'); expect(registry.getProduct('legacy_brl')?.currency).toBe('BRL');
expect(registry.getProduct('legacy_dkk')?.currency).toBe('DKK');
expect(registry.getProduct('legacy_inr')?.currency).toBe('INR'); expect(registry.getProduct('legacy_inr')?.currency).toBe('INR');
expect(registry.getProduct('legacy_nok')?.currency).toBe('NOK');
expect(registry.getProduct('legacy_pln')?.currency).toBe('PLN'); expect(registry.getProduct('legacy_pln')?.currency).toBe('PLN');
expect(registry.getProduct('legacy_sek')?.currency).toBe('SEK');
expect(registry.getProduct('legacy_try')?.currency).toBe('TRY'); expect(registry.getProduct('legacy_try')?.currency).toBe('TRY');
}); });
@@ -205,7 +211,7 @@ describe('ProductRegistry - legacy prices', () => {
test('no legacy price id is ever returned by either price getter, for any cycle or currency', () => { test('no legacy price id is ever returned by either price getter, for any cycle or currency', () => {
const registry = buildRegistry(MOCK_PRICES, MOCK_LEGACY_PRICES); const registry = buildRegistry(MOCK_PRICES, MOCK_LEGACY_PRICES);
const legacyIds = new Set(Object.values(MOCK_LEGACY_PRICES).flatMap((ids) => ids ?? [])); const legacyIds = new Set(Object.values(MOCK_LEGACY_PRICES).flatMap((ids) => ids ?? []));
const currencies = ['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']; const currencies = ['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'];
const offered: Array<string> = []; const offered: Array<string> = [];
for (const currency of currencies) { for (const currency of currencies) {
@@ -0,0 +1,288 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {APIErrorCodes} from '@fluxer/constants/src/ApiErrorCodes';
import type {
CurrentSubscriptionPriceResponse,
PriceIdsResponse,
} from '@fluxer/schema/src/domains/premium/PremiumSchemas';
import type {GeoipResult} from '@pkgs/geoip/src/GeoipLookup';
import {afterAll, beforeAll, beforeEach, describe, expect, test, vi} from 'vitest';
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
import {Config} from '../../Config';
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
import {createStripeApiHandlers, type StripeApiHandlers} from '../../test/msw/handlers/StripeApiHandlers';
import {server} from '../../test/msw/server';
import {HTTP_STATUS} from '../../test/TestConstants';
import {createBuilder} from '../../test/TestRequestBuilder';
const {lookupGeoipMock} = vi.hoisted(() => ({
lookupGeoipMock: vi.fn(),
}));
vi.mock('../../utils/IpUtils', async (importOriginal) => ({
...(await importOriginal<typeof import('../../utils/IpUtils')>()),
lookupGeoip: lookupGeoipMock,
}));
const MOCK_PRICES = {
monthlyUsd: 'price_nordic_monthly_usd',
yearlyUsd: 'price_nordic_yearly_usd',
monthlyEur: 'price_nordic_monthly_eur',
yearlyEur: 'price_nordic_yearly_eur',
monthlyDkk: 'price_nordic_monthly_dkk',
yearlyDkk: 'price_nordic_yearly_dkk',
monthlyNok: 'price_nordic_monthly_nok',
yearlyNok: 'price_nordic_yearly_nok',
monthlyPln: 'price_nordic_monthly_pln',
yearlyPln: 'price_nordic_yearly_pln',
monthlySek: 'price_nordic_monthly_sek',
yearlySek: 'price_nordic_yearly_sek',
gift1MonthUsd: 'price_nordic_gift_1_month_usd',
gift1YearUsd: 'price_nordic_gift_1_year_usd',
gift1MonthEur: 'price_nordic_gift_1_month_eur',
gift1YearEur: 'price_nordic_gift_1_year_eur',
};
const MOCK_PRICE_SEEDS = {
[MOCK_PRICES.monthlyUsd]: {unit_amount: 499, currency: 'usd', interval: 'month' as const},
[MOCK_PRICES.yearlyUsd]: {unit_amount: 4999, currency: 'usd', interval: 'year' as const},
[MOCK_PRICES.monthlyEur]: {unit_amount: 499, currency: 'eur', interval: 'month' as const},
[MOCK_PRICES.yearlyEur]: {unit_amount: 4999, currency: 'eur', interval: 'year' as const},
[MOCK_PRICES.monthlyDkk]: {unit_amount: 3700, currency: 'dkk', interval: 'month' as const},
[MOCK_PRICES.yearlyDkk]: {unit_amount: 37000, currency: 'dkk', interval: 'year' as const},
[MOCK_PRICES.monthlyNok]: {unit_amount: 5400, currency: 'nok', interval: 'month' as const},
[MOCK_PRICES.yearlyNok]: {unit_amount: 54000, currency: 'nok', interval: 'year' as const},
[MOCK_PRICES.monthlyPln]: {unit_amount: 1900, currency: 'pln', interval: 'month' as const},
[MOCK_PRICES.yearlyPln]: {unit_amount: 19000, currency: 'pln', interval: 'year' as const},
[MOCK_PRICES.monthlySek]: {unit_amount: 5400, currency: 'sek', interval: 'month' as const},
[MOCK_PRICES.yearlySek]: {unit_amount: 54000, currency: 'sek', interval: 'year' as const},
};
const EUR_SUBSCRIPTION_ID = 'sub_nordic_legacy_eur';
function geoipCountry(countryCode: string | null): GeoipResult {
return {
countryCode,
normalizedIp: '203.0.113.10',
city: null,
region: null,
countryName: null,
};
}
describe('Nordic localized currencies', () => {
let harness: ApiTestHarness;
let stripeHandlers: StripeApiHandlers;
let originalPrices: typeof Config.stripe.prices | undefined;
async function createPurchaser(): Promise<string> {
const account = await createTestAccount(harness);
await createBuilder(harness, account.token)
.post(`/test/users/${account.userId}/security-flags`)
.body({email_verified: true})
.execute();
return account.token;
}
function getPriceIds(countryCode: string | null): Promise<PriceIdsResponse> {
lookupGeoipMock.mockResolvedValue(geoipCountry(countryCode));
return createBuilder<PriceIdsResponse>(harness, '').get('/premium/price-ids').expect(HTTP_STATUS.OK).execute();
}
beforeAll(async () => {
originalPrices = Config.stripe.prices;
Config.stripe.prices = MOCK_PRICES;
harness = await createApiTestHarness();
});
afterAll(async () => {
await harness.shutdown();
Config.stripe.prices = originalPrices;
});
beforeEach(() => {
Config.stripe.prices = MOCK_PRICES;
lookupGeoipMock.mockReset();
lookupGeoipMock.mockResolvedValue(geoipCountry(null));
stripeHandlers = createStripeApiHandlers({
prices: MOCK_PRICE_SEEDS,
subscriptionsListEmpty: true,
subscriptions: {
[EUR_SUBSCRIPTION_ID]: {
customer: `cus_${EUR_SUBSCRIPTION_ID}`,
price_id: MOCK_PRICES.monthlyEur,
unit_amount: 499,
currency: 'eur',
interval: 'month',
item_id: `si_${EUR_SUBSCRIPTION_ID}`,
},
},
});
server.use(...stripeHandlers.handlers);
});
describe('country routing', () => {
test('Sweden resolves to the SEK subscription catalog', async () => {
const priceIds = await getPriceIds('SE');
expect(priceIds.currency).toBe('SEK');
expect(priceIds.monthly).toBe(MOCK_PRICES.monthlySek);
expect(priceIds.yearly).toBe(MOCK_PRICES.yearlySek);
});
test('Denmark resolves to the DKK subscription catalog', async () => {
const priceIds = await getPriceIds('DK');
expect(priceIds.currency).toBe('DKK');
expect(priceIds.monthly).toBe(MOCK_PRICES.monthlyDkk);
expect(priceIds.yearly).toBe(MOCK_PRICES.yearlyDkk);
});
test('Norway resolves to the NOK subscription catalog', async () => {
const priceIds = await getPriceIds('NO');
expect(priceIds.currency).toBe('NOK');
expect(priceIds.monthly).toBe(MOCK_PRICES.monthlyNok);
expect(priceIds.yearly).toBe(MOCK_PRICES.yearlyNok);
});
test('Poland still resolves to the PLN subscription catalog', async () => {
const priceIds = await getPriceIds('PL');
expect(priceIds.currency).toBe('PLN');
expect(priceIds.monthly).toBe(MOCK_PRICES.monthlyPln);
});
test.each(['DE', 'NL', 'FI', 'IE', 'IS'])('%s still resolves to the EUR subscription catalog', async (country) => {
const priceIds = await getPriceIds(country);
expect(priceIds.currency).toBe('EUR');
expect(priceIds.monthly).toBe(MOCK_PRICES.monthlyEur);
expect(priceIds.yearly).toBe(MOCK_PRICES.yearlyEur);
});
test.each(['SE', 'DK', 'NO'])('%s keeps gifts on the base currency', async (country) => {
const priceIds = await getPriceIds(country);
expect(priceIds.gift_currency).toBe('EUR');
expect(priceIds.gift_1_month).toBe(MOCK_PRICES.gift1MonthEur);
expect(priceIds.gift_1_year).toBe(MOCK_PRICES.gift1YearEur);
});
test('a Nordic gift falls through to USD when no EUR gift price is configured', async () => {
Config.stripe.prices = {
...MOCK_PRICES,
gift1MonthEur: undefined,
gift1YearEur: undefined,
};
const priceIds = await getPriceIds('SE');
expect(priceIds.currency).toBe('SEK');
expect(priceIds.gift_currency).toBe('USD');
expect(priceIds.gift_1_month).toBe(MOCK_PRICES.gift1MonthUsd);
});
test('Sweden falls back to EUR while the SEK prices are still unconfigured', async () => {
Config.stripe.prices = {
...MOCK_PRICES,
monthlySek: undefined,
yearlySek: undefined,
};
const priceIds = await getPriceIds('SE');
expect(priceIds.currency).toBe('EUR');
expect(priceIds.monthly).toBe(MOCK_PRICES.monthlyEur);
expect(priceIds.gift_currency).toBe('EUR');
});
});
describe('checkout enforcement', () => {
test('rejects the EUR subscription price for a purchase that geolocates to Sweden', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const token = await createPurchaser();
await createBuilder(harness, token)
.post('/stripe/checkout/subscription')
.body({price_id: MOCK_PRICES.monthlyEur, country_code: 'SE'})
.expect(HTTP_STATUS.BAD_REQUEST, APIErrorCodes.STRIPE_INVALID_PRODUCT_CONFIGURATION)
.execute();
expect(stripeHandlers.spies.createdCheckoutSessions).toHaveLength(0);
});
test('rejects the USD subscription price for a purchase that geolocates to Sweden', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const token = await createPurchaser();
await createBuilder(harness, token)
.post('/stripe/checkout/subscription')
.body({price_id: MOCK_PRICES.monthlyUsd, country_code: 'US'})
.expect(HTTP_STATUS.BAD_REQUEST, APIErrorCodes.STRIPE_INVALID_PRODUCT_CONFIGURATION)
.execute();
expect(stripeHandlers.spies.createdCheckoutSessions).toHaveLength(0);
});
test('rejects a neighbouring Nordic price for a purchase that geolocates to Sweden', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const token = await createPurchaser();
await createBuilder(harness, token)
.post('/stripe/checkout/subscription')
.body({price_id: MOCK_PRICES.monthlyDkk, country_code: 'DK'})
.expect(HTTP_STATUS.BAD_REQUEST, APIErrorCodes.STRIPE_INVALID_PRODUCT_CONFIGURATION)
.execute();
expect(stripeHandlers.spies.createdCheckoutSessions).toHaveLength(0);
});
test('accepts the SEK subscription price for a purchase that geolocates to Sweden', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const token = await createPurchaser();
const response = await createBuilder<{url: string}>(harness, token)
.post('/stripe/checkout/subscription')
.body({price_id: MOCK_PRICES.monthlySek, country_code: 'SE'})
.expect(HTTP_STATUS.OK)
.execute();
expect(response.url).toContain('checkout.stripe.com');
expect(stripeHandlers.spies.createdCheckoutSessions).toHaveLength(1);
});
test('accepts the base gift price from inside Sweden', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const token = await createPurchaser();
const response = await createBuilder<{url: string}>(harness, token)
.post('/stripe/checkout/gift')
.body({price_id: MOCK_PRICES.gift1MonthEur, country_code: 'SE'})
.expect(HTTP_STATUS.OK)
.execute();
expect(response.url).toContain('checkout.stripe.com');
expect(stripeHandlers.spies.createdCheckoutSessions).toHaveLength(1);
});
test('rejects the SEK subscription price on the gift endpoint', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const token = await createPurchaser();
await createBuilder(harness, token)
.post('/stripe/checkout/gift')
.body({price_id: MOCK_PRICES.monthlySek, country_code: 'SE'})
.expect(HTTP_STATUS.BAD_REQUEST, APIErrorCodes.STRIPE_INVALID_PRODUCT_CONFIGURATION)
.execute();
expect(stripeHandlers.spies.createdCheckoutSessions).toHaveLength(0);
});
});
describe('existing subscribers', () => {
test('a Swedish customer billed in EUR keeps the EUR price and is not repriced to SEK', async () => {
lookupGeoipMock.mockResolvedValue(geoipCountry('SE'));
const account = await createTestAccount(harness);
await createBuilder(harness, account.token)
.post(`/test/users/${account.userId}/premium`)
.body({
stripe_subscription_id: EUR_SUBSCRIPTION_ID,
premium_type: 1,
premium_billing_cycle: 'monthly',
premium_until: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
premium_will_cancel: false,
})
.execute();
const price = await createBuilder<CurrentSubscriptionPriceResponse>(harness, account.token)
.get('/premium/current-subscription-price')
.expect(HTTP_STATUS.OK)
.execute();
expect(price).toMatchObject({
price_id: MOCK_PRICES.monthlyEur,
currency: 'EUR',
billing_cycle: 'monthly',
is_grandfathered: false,
list_price_id: MOCK_PRICES.monthlyEur,
});
expect(stripeHandlers.spies.updatedSubscriptions).toHaveLength(0);
expect(stripeHandlers.spies.createdSubscriptionSchedules).toHaveLength(0);
});
});
});
@@ -801,13 +801,19 @@ export function createStripeApiHandlers(config: StripeApiMockConfig = {}): Strip
? 'eur' ? 'eur'
: normalizedPriceId.includes('brl') : normalizedPriceId.includes('brl')
? 'brl' ? 'brl'
: normalizedPriceId.includes('inr') : normalizedPriceId.includes('dkk')
? 'inr' ? 'dkk'
: normalizedPriceId.includes('pln') : normalizedPriceId.includes('inr')
? 'pln' ? 'inr'
: normalizedPriceId.includes('try') : normalizedPriceId.includes('nok')
? 'try' ? 'nok'
: 'usd', : normalizedPriceId.includes('pln')
? 'pln'
: normalizedPriceId.includes('sek')
? 'sek'
: normalizedPriceId.includes('try')
? 'try'
: 'usd',
interval: normalizedPriceId.includes('year') ? 'year' : 'month', interval: normalizedPriceId.includes('year') ? 'year' : 'month',
}; };
} }
@@ -1724,13 +1730,19 @@ export function createStripeApiHandlers(config: StripeApiMockConfig = {}): Strip
? 'eur' ? 'eur'
: normalizedPriceId.includes('brl') : normalizedPriceId.includes('brl')
? 'brl' ? 'brl'
: normalizedPriceId.includes('inr') : normalizedPriceId.includes('dkk')
? 'inr' ? 'dkk'
: normalizedPriceId.includes('pln') : normalizedPriceId.includes('inr')
? 'pln' ? 'inr'
: normalizedPriceId.includes('try') : normalizedPriceId.includes('nok')
? 'try' ? 'nok'
: 'usd'), : normalizedPriceId.includes('pln')
? 'pln'
: normalizedPriceId.includes('sek')
? 'sek'
: normalizedPriceId.includes('try')
? 'try'
: 'usd'),
unit_amount: overrides?.unit_amount ?? (normalizedPriceId.includes('year') ? 4999 : 499), unit_amount: overrides?.unit_amount ?? (normalizedPriceId.includes('year') ? 4999 : 499),
type: 'recurring', type: 'recurring',
recurring: { recurring: {
+15 -5
View File
@@ -2,7 +2,7 @@
import {isEuEeaCountryCode} from '@fluxer/constants/src/EuropeanEconomicArea'; import {isEuEeaCountryCode} from '@fluxer/constants/src/EuropeanEconomicArea';
export type Currency = 'USD' | 'EUR' | 'BRL' | 'INR' | 'PLN' | 'TRY'; export type Currency = 'USD' | 'EUR' | 'BRL' | 'DKK' | 'INR' | 'NOK' | 'PLN' | 'SEK' | 'TRY';
export function getCurrency(countryCode: string | null | undefined): Currency { export function getCurrency(countryCode: string | null | undefined): Currency {
return getCurrencyPreferences(countryCode)[0]; return getCurrencyPreferences(countryCode)[0];
@@ -16,12 +16,21 @@ export function getCurrencyPreferences(countryCode: string | null | undefined):
if (upperCode === 'BR') { if (upperCode === 'BR') {
return ['BRL', 'USD', 'EUR']; return ['BRL', 'USD', 'EUR'];
} }
if (upperCode === 'DK') {
return ['DKK', 'EUR', 'USD'];
}
if (upperCode === 'IN') { if (upperCode === 'IN') {
return ['INR', 'USD', 'EUR']; return ['INR', 'USD', 'EUR'];
} }
if (upperCode === 'NO') {
return ['NOK', 'EUR', 'USD'];
}
if (upperCode === 'PL') { if (upperCode === 'PL') {
return ['PLN', 'EUR', 'USD']; return ['PLN', 'EUR', 'USD'];
} }
if (upperCode === 'SE') {
return ['SEK', 'EUR', 'USD'];
}
if (upperCode === 'TR') { if (upperCode === 'TR') {
return ['TRY', 'USD', 'EUR']; return ['TRY', 'USD', 'EUR'];
} }
@@ -31,9 +40,10 @@ export function getCurrencyPreferences(countryCode: string | null | undefined):
return ['USD', 'EUR']; return ['USD', 'EUR'];
} }
const GIFT_ELIGIBLE_LOCALIZED_CURRENCIES = new Set<Currency>(['DKK', 'NOK', 'SEK']);
export function getGiftCurrencyPreferences(countryCode: string | null | undefined): Array<Currency> { export function getGiftCurrencyPreferences(countryCode: string | null | undefined): Array<Currency> {
if (countryCode && isEuEeaCountryCode(countryCode.toUpperCase())) { return getCurrencyPreferences(countryCode).filter(
return ['EUR', 'USD']; (currency) => currency === 'USD' || currency === 'EUR' || GIFT_ELIGIBLE_LOCALIZED_CURRENCIES.has(currency),
} );
return ['USD', 'EUR'];
} }
@@ -55,11 +55,11 @@ describe('getCurrency', () => {
it('returns EUR for Finland', () => { it('returns EUR for Finland', () => {
expect(getCurrency('FI')).toBe('EUR'); expect(getCurrency('FI')).toBe('EUR');
}); });
it('returns EUR for Sweden', () => { it('returns SEK for Sweden', () => {
expect(getCurrency('SE')).toBe('EUR'); expect(getCurrency('SE')).toBe('SEK');
}); });
it('returns EUR for Denmark', () => { it('returns DKK for Denmark', () => {
expect(getCurrency('DK')).toBe('EUR'); expect(getCurrency('DK')).toBe('DKK');
}); });
it('returns PLN for Poland', () => { it('returns PLN for Poland', () => {
expect(getCurrency('PL')).toBe('PLN'); expect(getCurrency('PL')).toBe('PLN');
@@ -76,8 +76,8 @@ describe('getCurrency', () => {
it('returns EUR for Romania', () => { it('returns EUR for Romania', () => {
expect(getCurrency('RO')).toBe('EUR'); expect(getCurrency('RO')).toBe('EUR');
}); });
it('returns EUR for Norway (EEA but not EU)', () => { it('returns NOK for Norway (EEA but not EU)', () => {
expect(getCurrency('NO')).toBe('EUR'); expect(getCurrency('NO')).toBe('NOK');
}); });
it('returns EUR for Iceland (EEA but not EU)', () => { it('returns EUR for Iceland (EEA but not EU)', () => {
expect(getCurrency('IS')).toBe('EUR'); expect(getCurrency('IS')).toBe('EUR');
@@ -128,7 +128,6 @@ describe('getCurrency', () => {
'HR', 'HR',
'CY', 'CY',
'CZ', 'CZ',
'DK',
'EE', 'EE',
'FI', 'FI',
'FR', 'FR',
@@ -147,10 +146,8 @@ describe('getCurrency', () => {
'SK', 'SK',
'SI', 'SI',
'ES', 'ES',
'SE',
'IS', 'IS',
'LI', 'LI',
'NO',
]; ];
for (const country of eeaCountries) { for (const country of eeaCountries) {
it(`returns EUR for ${country}`, () => { it(`returns EUR for ${country}`, () => {
@@ -160,16 +157,30 @@ describe('getCurrency', () => {
it('uses local currency for Poland', () => { it('uses local currency for Poland', () => {
expect(getCurrency('PL')).toBe('PLN'); expect(getCurrency('PL')).toBe('PLN');
}); });
it('uses local currency for Sweden', () => {
expect(getCurrency('SE')).toBe('SEK');
});
it('uses local currency for Denmark', () => {
expect(getCurrency('DK')).toBe('DKK');
});
it('uses local currency for Norway', () => {
expect(getCurrency('NO')).toBe('NOK');
});
}); });
}); });
describe('getGiftCurrencyPreferences', () => { describe('getGiftCurrencyPreferences', () => {
it('never offers a localized currency for a localized market', () => { it('never offers a localized currency that is cheaper than the base price', () => {
for (const country of ['BR', 'IN', 'PL', 'TR']) { for (const country of ['BR', 'IN', 'PL', 'TR']) {
expect(getGiftCurrencyPreferences(country)).not.toContain(getCurrencyPreferences(country)[0]); expect(getGiftCurrencyPreferences(country)).not.toContain(getCurrencyPreferences(country)[0]);
} }
}); });
it('uses EUR for EEA countries', () => { it('offers the localized currency where it is not cheaper than the base price', () => {
expect(getGiftCurrencyPreferences('SE')).toEqual(['SEK', 'EUR', 'USD']);
expect(getGiftCurrencyPreferences('DK')).toEqual(['DKK', 'EUR', 'USD']);
expect(getGiftCurrencyPreferences('NO')).toEqual(['NOK', 'EUR', 'USD']);
});
it('uses EUR for other EEA countries', () => {
expect(getGiftCurrencyPreferences('DE')).toEqual(['EUR', 'USD']); expect(getGiftCurrencyPreferences('DE')).toEqual(['EUR', 'USD']);
expect(getGiftCurrencyPreferences('PL')).toEqual(['EUR', 'USD']); expect(getGiftCurrencyPreferences('PL')).toEqual(['EUR', 'USD']);
}); });
@@ -184,7 +195,7 @@ describe('getGiftCurrencyPreferences', () => {
expect(getGiftCurrencyPreferences(undefined)).toEqual(['USD', 'EUR']); expect(getGiftCurrencyPreferences(undefined)).toEqual(['USD', 'EUR']);
}); });
it('is case insensitive', () => { it('is case insensitive', () => {
expect(getGiftCurrencyPreferences('de')).toEqual(['EUR', 'USD']); expect(getGiftCurrencyPreferences('se')).toEqual(['SEK', 'EUR', 'USD']);
expect(getGiftCurrencyPreferences('br')).toEqual(['USD', 'EUR']); expect(getGiftCurrencyPreferences('br')).toEqual(['USD', 'EUR']);
}); });
}); });
+1
View File
@@ -27,6 +27,7 @@ const MODULE_REGISTRY_TEST_FILES = [
'src/api/gif/GifRequestCountry.test.ts', 'src/api/gif/GifRequestCountry.test.ts',
'src/api/risk/__tests__/AccountPolicyService.test.ts', 'src/api/risk/__tests__/AccountPolicyService.test.ts',
'src/api/stripe/tests/StripeCheckoutCountryEnforcement.test.ts', 'src/api/stripe/tests/StripeCheckoutCountryEnforcement.test.ts',
'src/api/stripe/tests/StripeNordicCurrencies.test.ts',
]; ];
const INSTANCE_POLICY_TEST_FILES = [ const INSTANCE_POLICY_TEST_FILES = [
@@ -52,8 +52,11 @@ Every amount field is in the minor unit of the currency field its description na
| USD | United States dollar | | USD | United States dollar |
| EUR | Euro | | EUR | Euro |
| BRL | Brazilian real | | BRL | Brazilian real |
| DKK | Danish krone |
| INR | Indian rupee | | INR | Indian rupee |
| NOK | Norwegian krone |
| PLN | Polish zloty | | PLN | Polish zloty |
| SEK | Swedish krona |
| TRY | Turkish lira | | TRY | Turkish lira |
## Price IDs object ## Price IDs object
@@ -918,7 +918,7 @@ Default empty. The webhook signing secret. Not forwarded by the shipped Compose
Default `{}`. Every price ID at once. JSON object. The individual price variables are declared after it and win. Default `{}`. Every price ID at once. JSON object. The individual price variables are declared after it and win.
Twenty-eight individual price variables also exist, one per product and currency: `FLUXER_STRIPE_PRICE_MONTHLY_` and `FLUXER_STRIPE_PRICE_YEARLY_` in USD, EUR, BRL, INR, PLN, and TRY, `FLUXER_STRIPE_PRICE_VISIONARY_` and `FLUXER_STRIPE_PRICE_GIFT_VISIONARY_` in USD and EUR, and `FLUXER_STRIPE_PRICE_GIFT_1_MONTH_` and `FLUXER_STRIPE_PRICE_GIFT_1_YEAR_` in the same six currencies. Thirty-four individual price variables also exist, one per product and currency: `FLUXER_STRIPE_PRICE_MONTHLY_` and `FLUXER_STRIPE_PRICE_YEARLY_` in USD, EUR, BRL, DKK, INR, NOK, PLN, SEK, and TRY, `FLUXER_STRIPE_PRICE_VISIONARY_` and `FLUXER_STRIPE_PRICE_GIFT_VISIONARY_` in USD and EUR, and `FLUXER_STRIPE_PRICE_GIFT_1_MONTH_` and `FLUXER_STRIPE_PRICE_GIFT_1_YEAR_` in USD, EUR, BRL, INR, PLN, and TRY.
#### `FLUXER_STRIPE_LEGACY_PRICES` #### `FLUXER_STRIPE_LEGACY_PRICES`
@@ -301,14 +301,20 @@ const NAMED_FLUXER_ENV_OVERRIDES: Record<string, NamedEnvOverride> = {
FLUXER_STRIPE_PRICE_MONTHLY_USD: {path: ['integrations', 'stripe', 'prices', 'monthly_usd']}, FLUXER_STRIPE_PRICE_MONTHLY_USD: {path: ['integrations', 'stripe', 'prices', 'monthly_usd']},
FLUXER_STRIPE_PRICE_MONTHLY_EUR: {path: ['integrations', 'stripe', 'prices', 'monthly_eur']}, FLUXER_STRIPE_PRICE_MONTHLY_EUR: {path: ['integrations', 'stripe', 'prices', 'monthly_eur']},
FLUXER_STRIPE_PRICE_MONTHLY_BRL: {path: ['integrations', 'stripe', 'prices', 'monthly_brl']}, FLUXER_STRIPE_PRICE_MONTHLY_BRL: {path: ['integrations', 'stripe', 'prices', 'monthly_brl']},
FLUXER_STRIPE_PRICE_MONTHLY_DKK: {path: ['integrations', 'stripe', 'prices', 'monthly_dkk']},
FLUXER_STRIPE_PRICE_MONTHLY_INR: {path: ['integrations', 'stripe', 'prices', 'monthly_inr']}, FLUXER_STRIPE_PRICE_MONTHLY_INR: {path: ['integrations', 'stripe', 'prices', 'monthly_inr']},
FLUXER_STRIPE_PRICE_MONTHLY_NOK: {path: ['integrations', 'stripe', 'prices', 'monthly_nok']},
FLUXER_STRIPE_PRICE_MONTHLY_PLN: {path: ['integrations', 'stripe', 'prices', 'monthly_pln']}, FLUXER_STRIPE_PRICE_MONTHLY_PLN: {path: ['integrations', 'stripe', 'prices', 'monthly_pln']},
FLUXER_STRIPE_PRICE_MONTHLY_SEK: {path: ['integrations', 'stripe', 'prices', 'monthly_sek']},
FLUXER_STRIPE_PRICE_MONTHLY_TRY: {path: ['integrations', 'stripe', 'prices', 'monthly_try']}, FLUXER_STRIPE_PRICE_MONTHLY_TRY: {path: ['integrations', 'stripe', 'prices', 'monthly_try']},
FLUXER_STRIPE_PRICE_YEARLY_USD: {path: ['integrations', 'stripe', 'prices', 'yearly_usd']}, FLUXER_STRIPE_PRICE_YEARLY_USD: {path: ['integrations', 'stripe', 'prices', 'yearly_usd']},
FLUXER_STRIPE_PRICE_YEARLY_EUR: {path: ['integrations', 'stripe', 'prices', 'yearly_eur']}, FLUXER_STRIPE_PRICE_YEARLY_EUR: {path: ['integrations', 'stripe', 'prices', 'yearly_eur']},
FLUXER_STRIPE_PRICE_YEARLY_BRL: {path: ['integrations', 'stripe', 'prices', 'yearly_brl']}, FLUXER_STRIPE_PRICE_YEARLY_BRL: {path: ['integrations', 'stripe', 'prices', 'yearly_brl']},
FLUXER_STRIPE_PRICE_YEARLY_DKK: {path: ['integrations', 'stripe', 'prices', 'yearly_dkk']},
FLUXER_STRIPE_PRICE_YEARLY_INR: {path: ['integrations', 'stripe', 'prices', 'yearly_inr']}, FLUXER_STRIPE_PRICE_YEARLY_INR: {path: ['integrations', 'stripe', 'prices', 'yearly_inr']},
FLUXER_STRIPE_PRICE_YEARLY_NOK: {path: ['integrations', 'stripe', 'prices', 'yearly_nok']},
FLUXER_STRIPE_PRICE_YEARLY_PLN: {path: ['integrations', 'stripe', 'prices', 'yearly_pln']}, FLUXER_STRIPE_PRICE_YEARLY_PLN: {path: ['integrations', 'stripe', 'prices', 'yearly_pln']},
FLUXER_STRIPE_PRICE_YEARLY_SEK: {path: ['integrations', 'stripe', 'prices', 'yearly_sek']},
FLUXER_STRIPE_PRICE_YEARLY_TRY: {path: ['integrations', 'stripe', 'prices', 'yearly_try']}, FLUXER_STRIPE_PRICE_YEARLY_TRY: {path: ['integrations', 'stripe', 'prices', 'yearly_try']},
FLUXER_STRIPE_PRICE_VISIONARY_USD: {path: ['integrations', 'stripe', 'prices', 'visionary_usd']}, FLUXER_STRIPE_PRICE_VISIONARY_USD: {path: ['integrations', 'stripe', 'prices', 'visionary_usd']},
FLUXER_STRIPE_PRICE_VISIONARY_EUR: {path: ['integrations', 'stripe', 'prices', 'visionary_eur']}, FLUXER_STRIPE_PRICE_VISIONARY_EUR: {path: ['integrations', 'stripe', 'prices', 'visionary_eur']},
@@ -316,6 +322,12 @@ const NAMED_FLUXER_ENV_OVERRIDES: Record<string, NamedEnvOverride> = {
FLUXER_STRIPE_PRICE_GIFT_VISIONARY_EUR: {path: ['integrations', 'stripe', 'prices', 'gift_visionary_eur']}, FLUXER_STRIPE_PRICE_GIFT_VISIONARY_EUR: {path: ['integrations', 'stripe', 'prices', 'gift_visionary_eur']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_USD: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_usd']}, FLUXER_STRIPE_PRICE_GIFT_1_MONTH_USD: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_usd']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_EUR: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_eur']}, FLUXER_STRIPE_PRICE_GIFT_1_MONTH_EUR: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_eur']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_SEK: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_sek']},
FLUXER_STRIPE_PRICE_GIFT_1_YEAR_SEK: {path: ['integrations', 'stripe', 'prices', 'gift_1_year_sek']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_DKK: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_dkk']},
FLUXER_STRIPE_PRICE_GIFT_1_YEAR_DKK: {path: ['integrations', 'stripe', 'prices', 'gift_1_year_dkk']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_NOK: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_nok']},
FLUXER_STRIPE_PRICE_GIFT_1_YEAR_NOK: {path: ['integrations', 'stripe', 'prices', 'gift_1_year_nok']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_BRL: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_brl']}, FLUXER_STRIPE_PRICE_GIFT_1_MONTH_BRL: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_brl']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_INR: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_inr']}, FLUXER_STRIPE_PRICE_GIFT_1_MONTH_INR: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_inr']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_PLN: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_pln']}, FLUXER_STRIPE_PRICE_GIFT_1_MONTH_PLN: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_pln']},
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ar\n" "Language: ar\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2372,14 +2372,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "إذا كنت تكتب عن {product_name}، راسلنا على {email}. سيقرأ رسالتك شخص حقيقي." msgstr "إذا كنت تكتب عن {product_name}، راسلنا على {email}. سيقرأ رسالتك شخص حقيقي."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"الاشتراك نفسه متاح أيضًا بعملة {base_currency_code}، بسعر {base_monthly_price} شهريًا أو {base_yearly_price} سنويًا."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: bg\n" "Language: bg\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2388,14 +2388,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Ако пишеш материал за {product_name}, изпрати имейл на {email}. Чете го истински човек." msgstr "Ако пишеш материал за {product_name}, изпрати имейл на {email}. Чете го истински човек."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: cs\n" "Language: cs\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2381,14 +2381,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Píšeš o {product_name}? Napiš nám na {email}. Čte to skutečný člověk." msgstr "Píšeš o {product_name}? Napiš nám na {email}. Čte to skutečný člověk."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Stejné předplatné se prodává i v měně {base_currency_code}, a to za {base_monthly_price} měsíčně nebo {base_yearly_price} na rok."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: da\n" "Language: da\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2388,14 +2388,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Skriver du om {product_name}, så send en mail til {email}. Der sidder et rigtigt menneske og læser den." "Skriver du om {product_name}, så send en mail til {email}. Der sidder et rigtigt menneske og læser den."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Det samme abonnement sælges også i {base_currency_code}, til {base_monthly_price} om måneden eller {base_yearly_price} for et år."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: de\n" "Language: de\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2396,14 +2396,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Wenn du über {product_name} schreibst, schreib uns an {email}. Ein echter Mensch liest mit." "Wenn du über {product_name} schreibst, schreib uns an {email}. Ein echter Mensch liest mit."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Dasselbe Abo wird auch in {base_currency_code} verkauft, für {base_monthly_price} im Monat oder {base_yearly_price} im Jahr."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: el\n" "Language: el\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2405,14 +2405,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Αν γράφεις για το {product_name}, στείλε email στο {email}. Το διαβάζει πραγματικός άνθρωπος." "Αν γράφεις για το {product_name}, στείλε email στο {email}. Το διαβάζει πραγματικός άνθρωπος."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Η ίδια συνδρομή πωλείται και σε {base_currency_code}, με {base_monthly_price} τον μήνα ή {base_yearly_price} τον χρόνο."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: en-GB\n" "Language: en-GB\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2380,14 +2380,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "If you are writing about {product_name}, email {email}. A real person reads it." msgstr "If you are writing about {product_name}, email {email}. A real person reads it."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: en-US\n" "Language: en-US\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2380,14 +2380,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "If you are writing about {product_name}, email {email}. A real person reads it." msgstr "If you are writing about {product_name}, email {email}. A real person reads it."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: es-419\n" "Language: es-419\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2393,14 +2393,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Si estás escribiendo sobre {product_name}, escríbenos a {email}. Una persona real lo lee." msgstr "Si estás escribiendo sobre {product_name}, escríbenos a {email}. Una persona real lo lee."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"La misma suscripción también se vende en {base_currency_code}, a {base_monthly_price} al mes o {base_yearly_price} al año."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: es-ES\n" "Language: es-ES\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2395,14 +2395,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Si estás escribiendo sobre {product_name}, escribe a {email}. Lo lee una persona de verdad." "Si estás escribiendo sobre {product_name}, escribe a {email}. Lo lee una persona de verdad."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"La misma suscripción también se vende en {base_currency_code}, por {base_monthly_price} al mes o {base_yearly_price} al año."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: fi\n" "Language: fi\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2394,14 +2394,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Jos kirjoitat {product_name}-palvelusta, lähetä sähköpostia osoitteeseen {email}. Viestin lukee oikea ihminen." "Jos kirjoitat {product_name}-palvelusta, lähetä sähköpostia osoitteeseen {email}. Viestin lukee oikea ihminen."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Sama tilaus on myynnissä myös valuutassa {base_currency_code} hintaan {base_monthly_price} kuukaudessa tai {base_yearly_price} vuodessa."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: fr\n" "Language: fr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2400,14 +2400,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Si tu prépares un sujet sur {product_name}, écris à {email}. Une vraie personne le lit." msgstr "Si tu prépares un sujet sur {product_name}, écris à {email}. Une vraie personne le lit."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Le même abonnement est aussi vendu en {base_currency_code}, à {base_monthly_price} par mois ou {base_yearly_price} par an."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: he\n" "Language: he\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2364,14 +2364,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "אם אתם כותבים על {product_name}, שלחו אימייל ל-{email}. אדם אמיתי קורא אותו." msgstr "אם אתם כותבים על {product_name}, שלחו אימייל ל-{email}. אדם אמיתי קורא אותו."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"אותו מנוי נמכר גם ב-{base_currency_code}, במחיר {base_monthly_price} לחודש או {base_yearly_price} לשנה."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: hi\n" "Language: hi\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2383,14 +2383,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"अगर आप {product_name} के बारे में लिख रहे हैं, तो {email} पर ईमेल करें। इसे एक असली इंसान पढ़ता है।" "अगर आप {product_name} के बारे में लिख रहे हैं, तो {email} पर ईमेल करें। इसे एक असली इंसान पढ़ता है।"
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"यही सब्सक्रिप्शन {base_currency_code} में भी मिलता है — {base_monthly_price} प्रति माह या {base_yearly_price} प्रति वर्ष।"
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: hr\n" "Language: hr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2386,14 +2386,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Ako pišeš o {product_name}u, javi se na {email}. Čita ih prava osoba." msgstr "Ako pišeš o {product_name}u, javi se na {email}. Čita ih prava osoba."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Ista se pretplata prodaje i u valuti {base_currency_code}, po cijeni od {base_monthly_price} mjesečno ili {base_yearly_price} godišnje."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: hu\n" "Language: hu\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2395,14 +2395,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Ha a {product_name}-ről írsz, írj a következő címre: {email}. Valódi ember olvassa." msgstr "Ha a {product_name}-ről írsz, írj a következő címre: {email}. Valódi ember olvassa."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Ugyanez az előfizetés {base_currency_code} pénznemben is megvásárolható, havi {base_monthly_price} vagy éves {base_yearly_price} áron."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: id\n" "Language: id\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2384,14 +2384,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Kalau kamu sedang menulis tentang {product_name}, kirim email ke {email}. Ada orang sungguhan yang membacanya." "Kalau kamu sedang menulis tentang {product_name}, kirim email ke {email}. Ada orang sungguhan yang membacanya."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Langganan yang sama juga dijual dalam {base_currency_code}, seharga {base_monthly_price} per bulan atau {base_yearly_price} per tahun."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: it\n" "Language: it\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2393,14 +2393,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Se stai scrivendo di {product_name}, scrivi a {email}. A leggere c'è una persona vera." msgstr "Se stai scrivendo di {product_name}, scrivi a {email}. A leggere c'è una persona vera."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Lo stesso abbonamento è venduto anche in {base_currency_code}, a {base_monthly_price} al mese o {base_yearly_price} per un anno."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ja\n" "Language: ja\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2346,13 +2346,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "{product_name}について記事を書かれる方は、{email}までメールをお送りください。実際に担当者が目を通します。" msgstr "{product_name}について記事を書かれる方は、{email}までメールをお送りください。実際に担当者が目を通します。"
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr "同じサブスクリプションは{base_currency_code}でも販売しており、月額{base_monthly_price}または年額{base_yearly_price}です。"
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ko\n" "Language: ko\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2344,13 +2344,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "{product_name}에 대한 기사를 준비 중이시라면 {email}로 메일을 보내 주세요. 실제 담당자가 읽습니다." msgstr "{product_name}에 대한 기사를 준비 중이시라면 {email}로 메일을 보내 주세요. 실제 담당자가 읽습니다."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr "동일한 구독을 {base_currency_code}로도 판매하며, 월 {base_monthly_price} 또는 연 {base_yearly_price}입니다."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: lt\n" "Language: lt\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2389,14 +2389,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Jei rašai apie {product_name}, parašyk adresu {email}. Laiškus skaito tikras žmogus." msgstr "Jei rašai apie {product_name}, parašyk adresu {email}. Laiškus skaito tikras žmogus."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Ta pati prenumerata parduodama ir {base_currency_code} valiuta: {base_monthly_price} per mėnesį arba {base_yearly_price} per metus."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: nl\n" "Language: nl\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2390,14 +2390,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Schrijf je over {product_name}? Mail dan naar {email}. Er leest een echt mens mee." msgstr "Schrijf je over {product_name}? Mail dan naar {email}. Er leest een echt mens mee."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Hetzelfde abonnement wordt ook verkocht in {base_currency_code}, voor {base_monthly_price} per maand of {base_yearly_price} per jaar."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: no\n" "Language: no\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2387,14 +2387,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Skriver du om {product_name}? Send en e-post til {email}. Det er et ekte menneske som leser den." "Skriver du om {product_name}? Send en e-post til {email}. Det er et ekte menneske som leser den."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Det samme abonnementet selges også i {base_currency_code}, til {base_monthly_price} i måneden eller {base_yearly_price} for et år."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: pl\n" "Language: pl\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2391,14 +2391,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Jeśli piszesz o {product_name}, napisz na {email}. Czyta to prawdziwa osoba." msgstr "Jeśli piszesz o {product_name}, napisz na {email}. Czyta to prawdziwa osoba."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Ta sama subskrypcja jest też sprzedawana w {base_currency_code}: {base_monthly_price} miesięcznie lub {base_yearly_price} rocznie."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: pt-BR\n" "Language: pt-BR\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2392,14 +2392,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Se você está escrevendo sobre o {product_name}, escreva para {email}. Uma pessoa de verdade lê as mensagens." "Se você está escrevendo sobre o {product_name}, escreva para {email}. Uma pessoa de verdade lê as mensagens."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"A mesma assinatura também é vendida em {base_currency_code}, a {base_monthly_price} por mês ou {base_yearly_price} por ano."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ro\n" "Language: ro\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2396,14 +2396,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"Dacă scrii despre {product_name}, trimite-ne un e-mail la {email}. Îl citește un om adevărat." "Dacă scrii despre {product_name}, trimite-ne un e-mail la {email}. Îl citește un om adevărat."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Același abonament este vândut și în {base_currency_code}, la {base_monthly_price} pe lună sau {base_yearly_price} pe an."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ru\n" "Language: ru\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2389,14 +2389,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Пишешь материал о {product_name}? Напиши нам на {email}. Письма читает живой человек." msgstr "Пишешь материал о {product_name}? Напиши нам на {email}. Письма читает живой человек."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Эта же подписка продаётся и в {base_currency_code}: {base_monthly_price} в месяц или {base_yearly_price} в год."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: sv-SE\n" "Language: sv-SE\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2390,14 +2390,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Om du skriver om {product_name}, mejla {email}. En riktig människa läser det." msgstr "Om du skriver om {product_name}, mejla {email}. En riktig människa läser det."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Samma prenumeration säljs även i {base_currency_code}, för {base_monthly_price} i månaden eller {base_yearly_price} för ett år."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: th\n" "Language: th\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2378,14 +2378,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "หากคุณกำลังเขียนถึง {product_name} ส่งอีเมลมาที่ {email} มีคนจริงๆ อ่านทุกฉบับ" msgstr "หากคุณกำลังเขียนถึง {product_name} ส่งอีเมลมาที่ {email} มีคนจริงๆ อ่านทุกฉบับ"
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"การสมัครสมาชิกแบบเดียวกันนี้มีจำหน่ายในสกุลเงิน {base_currency_code} ด้วย ที่ {base_monthly_price} ต่อเดือน หรือ {base_yearly_price} ต่อปี"
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: tr\n" "Language: tr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2386,14 +2386,6 @@ msgid "If you are writing about {product_name}, email {email}. A real person rea
msgstr "" msgstr ""
"{product_name} hakkında yazıyorsan {email} adresine e-posta gönder. Mesajını gerçek bir insan okuyor." "{product_name} hakkında yazıyorsan {email} adresine e-posta gönder. Mesajını gerçek bir insan okuyor."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Aynı abonelik {base_currency_code} cinsinden de satılıyor: ayda {base_monthly_price} veya yılda {base_yearly_price}."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: uk\n" "Language: uk\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2389,14 +2389,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Якщо ти пишеш про {product_name}, напиши на {email}. Це читає жива людина." msgstr "Якщо ти пишеш про {product_name}, напиши на {email}. Це читає жива людина."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Ця сама передплата також продається у {base_currency_code}: {base_monthly_price} на місяць або {base_yearly_price} на рік."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: vi\n" "Language: vi\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2390,14 +2390,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "Nếu bạn đang viết về {product_name}, hãy gửi email tới {email}. Một người thật sẽ đọc nó." msgstr "Nếu bạn đang viết về {product_name}, hãy gửi email tới {email}. Một người thật sẽ đọc nó."
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr ""
"Cùng gói đăng ký này cũng được bán bằng {base_currency_code}, với giá {base_monthly_price} mỗi tháng hoặc {base_yearly_price} mỗi năm."
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: zh-CN\n" "Language: zh-CN\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2335,13 +2335,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "如果你要撰写关于 {product_name} 的报道,请发送邮件至 {email}。会有真人阅读。" msgstr "如果你要撰写关于 {product_name} 的报道,请发送邮件至 {email}。会有真人阅读。"
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr "同样的订阅也以 {base_currency_code} 出售,每月 {base_monthly_price} 或每年 {base_yearly_price}。"
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: fluxer-marketing\n" "Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n" "POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n" "PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: zh-TW\n" "Language: zh-TW\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -2335,13 +2335,6 @@ msgctxt "press_branding.contact.story_prompt_message"
msgid "If you are writing about {product_name}, email {email}. A real person reads it." msgid "If you are writing about {product_name}, email {email}. A real person reads it."
msgstr "如果你正在撰寫關於 {product_name} 的報導,請寄信到 {email},會有真人閱讀。" msgstr "如果你正在撰寫關於 {product_name} 的報導,請寄信到 {email},會有真人閱讀。"
#. Body copy in pricing UI explaining the base-currency checkout option. Preserve all currency and price placeholders exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.base_currency_also_available
msgctxt "pricing_and_tiers.billing.base_currency_also_available"
msgid ""
"The same subscription is also sold in {base_currency_code}, at {base_monthly_price} a month or {base_yearly_price} for a year."
msgstr "同樣的訂閱方案也以 {base_currency_code} 販售,每月 {base_monthly_price},或每年 {base_yearly_price}。"
#. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly. #. Compact monthly price label in pricing UI. Preserve the monthly price placeholder exactly.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price #: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price" msgctxt "pricing_and_tiers.billing.monthly_price"
@@ -29,8 +29,10 @@ export const PriceIdsResponse = z.object({
.nullish() .nullish()
.describe('Gift 1 month price amount in the currency minor unit'), .describe('Gift 1 month price amount in the currency minor unit'),
gift_1_year_amount_minor: z.number().int().nullish().describe('Gift 1 year price amount in the currency minor unit'), gift_1_year_amount_minor: z.number().int().nullish().describe('Gift 1 year price amount in the currency minor unit'),
currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency for the prices'), currency: z.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY']).describe('Currency for the prices'),
gift_currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency for gift prices'), gift_currency: z
.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.describe('Currency for gift prices'),
}); });
export type PriceIdsResponse = z.infer<typeof PriceIdsResponse>; export type PriceIdsResponse = z.infer<typeof PriceIdsResponse>;
@@ -83,7 +85,9 @@ export const CurrentSubscriptionPriceResponse = z
.object({ .object({
price_id: z.string().describe('The Stripe price ID the user is currently billed against'), price_id: z.string().describe('The Stripe price ID the user is currently billed against'),
amount_minor: z.number().int().describe('The amount the user is actually charged, in the currency minor unit'), amount_minor: z.number().int().describe('The amount the user is actually charged, in the currency minor unit'),
currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency of the charged amount'), currency: z
.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.describe('Currency of the charged amount'),
billing_cycle: z.enum(['monthly', 'yearly']).describe('The recurring billing cycle of the active subscription'), billing_cycle: z.enum(['monthly', 'yearly']).describe('The recurring billing cycle of the active subscription'),
is_grandfathered: z is_grandfathered: z
.boolean() .boolean()
@@ -119,7 +123,10 @@ export const PendingSubscriptionChangeResponse = z
.int() .int()
.nullable() .nullable()
.describe('Unit amount of the price that will be used after the change, in the currency minor unit'), .describe('Unit amount of the price that will be used after the change, in the currency minor unit'),
currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).nullable().describe('Currency for the pending change'), currency: z
.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.nullable()
.describe('Currency for the pending change'),
initial_amount_minor: z initial_amount_minor: z
.number() .number()
.int() .int()
@@ -187,7 +194,7 @@ export const ListPriceSwitchState = z.object({
.nullable() .nullable()
.describe('Current list price for the same cycle and currency, in the currency minor unit'), .describe('Current list price for the same cycle and currency, in the currency minor unit'),
currency: z currency: z
.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']) .enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.nullable() .nullable()
.describe('Currency of both the current and the list amount'), .describe('Currency of both the current and the list amount'),
billing_cycle: z.enum(['monthly', 'yearly']).nullable().describe('Recurring billing cycle the switch applies to'), billing_cycle: z.enum(['monthly', 'yearly']).nullable().describe('Recurring billing cycle the switch applies to'),
@@ -206,7 +213,9 @@ export const SwitchToListPriceResponse = z.discriminatedUnion('status', [
target_price_id: z.string().describe('Stripe price ID the subscription will be billed against after the switch'), target_price_id: z.string().describe('Stripe price ID the subscription will be billed against after the switch'),
target_amount_minor: z.number().int().describe('Amount billed after the switch, in the currency minor unit'), target_amount_minor: z.number().int().describe('Amount billed after the switch, in the currency minor unit'),
current_amount_minor: z.number().int().describe('Amount billed before the switch, in the currency minor unit'), current_amount_minor: z.number().int().describe('Amount billed before the switch, in the currency minor unit'),
currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency of both amounts'), currency: z
.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.describe('Currency of both amounts'),
}), }),
z.object({ z.object({
status: z.literal('already_scheduled').describe('The switch was already scheduled by an earlier request'), status: z.literal('already_scheduled').describe('The switch was already scheduled by an earlier request'),
@@ -214,7 +223,9 @@ export const SwitchToListPriceResponse = z.discriminatedUnion('status', [
target_price_id: z.string().describe('Stripe price ID the subscription will be billed against after the switch'), target_price_id: z.string().describe('Stripe price ID the subscription will be billed against after the switch'),
target_amount_minor: z.number().int().describe('Amount billed after the switch, in the currency minor unit'), target_amount_minor: z.number().int().describe('Amount billed after the switch, in the currency minor unit'),
current_amount_minor: z.number().int().describe('Amount billed before the switch, in the currency minor unit'), current_amount_minor: z.number().int().describe('Amount billed before the switch, in the currency minor unit'),
currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency of both amounts'), currency: z
.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.describe('Currency of both amounts'),
}), }),
z.object({ z.object({
status: z.literal('ineligible').describe('The subscription cannot be moved to the current list price'), status: z.literal('ineligible').describe('The subscription cannot be moved to the current list price'),