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,
monthlyEur: master.integrations.stripe.prices.monthly_eur,
monthlyBrl: master.integrations.stripe.prices.monthly_brl,
monthlyDkk: master.integrations.stripe.prices.monthly_dkk,
monthlyInr: master.integrations.stripe.prices.monthly_inr,
monthlyNok: master.integrations.stripe.prices.monthly_nok,
monthlyPln: master.integrations.stripe.prices.monthly_pln,
monthlySek: master.integrations.stripe.prices.monthly_sek,
monthlyTry: master.integrations.stripe.prices.monthly_try,
yearlyUsd: master.integrations.stripe.prices.yearly_usd,
yearlyEur: master.integrations.stripe.prices.yearly_eur,
yearlyBrl: master.integrations.stripe.prices.yearly_brl,
yearlyDkk: master.integrations.stripe.prices.yearly_dkk,
yearlyInr: master.integrations.stripe.prices.yearly_inr,
yearlyNok: master.integrations.stripe.prices.yearly_nok,
yearlyPln: master.integrations.stripe.prices.yearly_pln,
yearlySek: master.integrations.stripe.prices.yearly_sek,
yearlyTry: master.integrations.stripe.prices.yearly_try,
gift1MonthUsd: master.integrations.stripe.prices.gift_1_month_usd,
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,
gift1MonthInr: master.integrations.stripe.prices.gift_1_month_inr,
gift1MonthPln: master.integrations.stripe.prices.gift_1_month_pln,
+12
View File
@@ -226,17 +226,29 @@ export interface APIConfig {
monthlyUsd?: string;
monthlyEur?: string;
monthlyBrl?: string;
monthlyDkk?: string;
monthlyInr?: string;
monthlyNok?: string;
monthlyPln?: string;
monthlySek?: string;
monthlyTry?: string;
yearlyUsd?: string;
yearlyEur?: string;
yearlyBrl?: string;
yearlyDkk?: string;
yearlyInr?: string;
yearlyNok?: string;
yearlyPln?: string;
yearlySek?: string;
yearlyTry?: string;
gift1MonthUsd?: string;
gift1MonthEur?: string;
gift1MonthSek?: string;
gift1YearSek?: string;
gift1MonthDkk?: string;
gift1YearDkk?: string;
gift1MonthNok?: string;
gift1YearNok?: string;
gift1MonthBrl?: string;
gift1MonthInr?: string;
gift1MonthPln?: string;
+14 -14
View File
@@ -32064,9 +32064,9 @@
"description": "The amount the user is actually charged, in the currency minor unit"
},
"currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"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"
},
"billing_cycle": {
@@ -32345,9 +32345,9 @@
"currency": {
"anyOf": [
{
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"]
"x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"]
},
{"type": "null"}
],
@@ -32418,9 +32418,9 @@
"currency": {
"anyOf": [
{
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"type": "string",
"x-enumNames": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"]
"x-enumNames": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"]
},
{"type": "null"}
],
@@ -32662,15 +32662,15 @@
"description": "Gift 1 year price amount in the currency minor unit"
},
"currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"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"
},
"gift_currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"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"
}
},
@@ -32749,9 +32749,9 @@
"description": "Amount billed before the switch, in the currency minor unit"
},
"currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"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"
}
},
@@ -32788,9 +32788,9 @@
"description": "Amount billed before the switch, in the currency minor unit"
},
"currency": {
"enum": ["USD", "EUR", "BRL", "INR", "PLN", "TRY"],
"enum": ["USD", "EUR", "BRL", "DKK", "INR", "NOK", "PLN", "SEK", "TRY"],
"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"
}
},
@@ -56,8 +56,11 @@ const LEGACY_SLOT_CURRENCIES: Record<string, Currency | undefined> = {
usd: 'USD',
eur: 'EUR',
brl: 'BRL',
dkk: 'DKK',
inr: 'INR',
nok: 'NOK',
pln: 'PLN',
sek: 'SEK',
try: 'TRY',
};
@@ -109,6 +112,14 @@ export class ProductRegistry {
currency: 'BRL',
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, {
type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -117,6 +128,14 @@ export class ProductRegistry {
currency: 'INR',
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, {
type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -125,6 +144,14 @@ export class ProductRegistry {
currency: 'PLN',
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, {
type: ProductType.MONTHLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -157,6 +184,14 @@ export class ProductRegistry {
currency: 'BRL',
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, {
type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -165,6 +200,14 @@ export class ProductRegistry {
currency: 'INR',
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, {
type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -173,6 +216,14 @@ export class ProductRegistry {
currency: 'PLN',
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, {
type: ProductType.YEARLY_SUBSCRIPTION,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -209,6 +260,48 @@ export class ProductRegistry {
isGift: true,
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, {
type: ProductType.GIFT_1_MONTH,
premiumType: UserPremiumTypes.SUBSCRIPTION,
@@ -319,12 +412,21 @@ export class ProductRegistry {
if (normalizedCurrency === 'brl') {
return billingCycle === 'monthly' ? (prices.monthlyBrl ?? null) : (prices.yearlyBrl ?? null);
}
if (normalizedCurrency === 'dkk') {
return billingCycle === 'monthly' ? (prices.monthlyDkk ?? null) : (prices.yearlyDkk ?? null);
}
if (normalizedCurrency === 'inr') {
return billingCycle === 'monthly' ? (prices.monthlyInr ?? null) : (prices.yearlyInr ?? null);
}
if (normalizedCurrency === 'nok') {
return billingCycle === 'monthly' ? (prices.monthlyNok ?? null) : (prices.yearlyNok ?? null);
}
if (normalizedCurrency === 'pln') {
return billingCycle === 'monthly' ? (prices.monthlyPln ?? null) : (prices.yearlyPln ?? null);
}
if (normalizedCurrency === 'sek') {
return billingCycle === 'monthly' ? (prices.monthlySek ?? null) : (prices.yearlySek ?? null);
}
if (normalizedCurrency === 'try') {
return billingCycle === 'monthly' ? (prices.monthlyTry ?? null) : (prices.yearlyTry ?? null);
}
@@ -349,6 +451,15 @@ export class ProductRegistry {
if (normalizedCurrency === 'inr') {
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') {
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 === 'EUR' ||
currency === 'BRL' ||
currency === 'DKK' ||
currency === 'INR' ||
currency === 'NOK' ||
currency === 'PLN' ||
currency === 'SEK' ||
currency === 'TRY'
) {
return currency;
@@ -1108,6 +1108,15 @@ export class StripeCheckoutService {
yearly: prices.yearlyBrl,
currency,
};
case 'DKK':
if (!prices.monthlyDkk || !prices.yearlyDkk) {
return null;
}
return {
monthly: prices.monthlyDkk,
yearly: prices.yearlyDkk,
currency,
};
case 'INR':
if (!prices.monthlyInr || !prices.yearlyInr) {
return null;
@@ -1117,6 +1126,15 @@ export class StripeCheckoutService {
yearly: prices.yearlyInr,
currency,
};
case 'NOK':
if (!prices.monthlyNok || !prices.yearlyNok) {
return null;
}
return {
monthly: prices.monthlyNok,
yearly: prices.yearlyNok,
currency,
};
case 'PLN':
if (!prices.monthlyPln || !prices.yearlyPln) {
return null;
@@ -1126,6 +1144,15 @@ export class StripeCheckoutService {
yearly: prices.yearlyPln,
currency,
};
case 'SEK':
if (!prices.monthlySek || !prices.yearlySek) {
return null;
}
return {
monthly: prices.monthlySek,
yearly: prices.yearlySek,
currency,
};
case 'TRY':
if (!prices.monthlyTry || !prices.yearlyTry) {
return null;
@@ -1175,6 +1202,33 @@ export class StripeCheckoutService {
gift_1_year: prices.gift1YearInr,
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':
if (!prices.gift1MonthPln || !prices.gift1YearPln) {
return null;
@@ -119,16 +119,22 @@ describe('ProductRegistry - legacy prices', () => {
monthly_usd: ['legacy_usd'],
monthly_eur: ['legacy_eur'],
monthly_brl: ['legacy_brl'],
monthly_dkk: ['legacy_dkk'],
monthly_inr: ['legacy_inr'],
monthly_nok: ['legacy_nok'],
monthly_pln: ['legacy_pln'],
monthly_sek: ['legacy_sek'],
monthly_try: ['legacy_try'],
},
);
expect(registry.getProduct('legacy_usd')?.currency).toBe('USD');
expect(registry.getProduct('legacy_eur')?.currency).toBe('EUR');
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_nok')?.currency).toBe('NOK');
expect(registry.getProduct('legacy_pln')?.currency).toBe('PLN');
expect(registry.getProduct('legacy_sek')?.currency).toBe('SEK');
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', () => {
const registry = buildRegistry(MOCK_PRICES, MOCK_LEGACY_PRICES);
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> = [];
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'
: normalizedPriceId.includes('brl')
? 'brl'
: normalizedPriceId.includes('inr')
? 'inr'
: normalizedPriceId.includes('pln')
? 'pln'
: normalizedPriceId.includes('try')
? 'try'
: 'usd',
: normalizedPriceId.includes('dkk')
? 'dkk'
: normalizedPriceId.includes('inr')
? 'inr'
: normalizedPriceId.includes('nok')
? 'nok'
: normalizedPriceId.includes('pln')
? 'pln'
: normalizedPriceId.includes('sek')
? 'sek'
: normalizedPriceId.includes('try')
? 'try'
: 'usd',
interval: normalizedPriceId.includes('year') ? 'year' : 'month',
};
}
@@ -1724,13 +1730,19 @@ export function createStripeApiHandlers(config: StripeApiMockConfig = {}): Strip
? 'eur'
: normalizedPriceId.includes('brl')
? 'brl'
: normalizedPriceId.includes('inr')
? 'inr'
: normalizedPriceId.includes('pln')
? 'pln'
: normalizedPriceId.includes('try')
? 'try'
: 'usd'),
: normalizedPriceId.includes('dkk')
? 'dkk'
: normalizedPriceId.includes('inr')
? 'inr'
: normalizedPriceId.includes('nok')
? 'nok'
: normalizedPriceId.includes('pln')
? 'pln'
: normalizedPriceId.includes('sek')
? 'sek'
: normalizedPriceId.includes('try')
? 'try'
: 'usd'),
unit_amount: overrides?.unit_amount ?? (normalizedPriceId.includes('year') ? 4999 : 499),
type: 'recurring',
recurring: {
+15 -5
View File
@@ -2,7 +2,7 @@
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 {
return getCurrencyPreferences(countryCode)[0];
@@ -16,12 +16,21 @@ export function getCurrencyPreferences(countryCode: string | null | undefined):
if (upperCode === 'BR') {
return ['BRL', 'USD', 'EUR'];
}
if (upperCode === 'DK') {
return ['DKK', 'EUR', 'USD'];
}
if (upperCode === 'IN') {
return ['INR', 'USD', 'EUR'];
}
if (upperCode === 'NO') {
return ['NOK', 'EUR', 'USD'];
}
if (upperCode === 'PL') {
return ['PLN', 'EUR', 'USD'];
}
if (upperCode === 'SE') {
return ['SEK', 'EUR', 'USD'];
}
if (upperCode === 'TR') {
return ['TRY', 'USD', 'EUR'];
}
@@ -31,9 +40,10 @@ export function getCurrencyPreferences(countryCode: string | null | undefined):
return ['USD', 'EUR'];
}
const GIFT_ELIGIBLE_LOCALIZED_CURRENCIES = new Set<Currency>(['DKK', 'NOK', 'SEK']);
export function getGiftCurrencyPreferences(countryCode: string | null | undefined): Array<Currency> {
if (countryCode && isEuEeaCountryCode(countryCode.toUpperCase())) {
return ['EUR', 'USD'];
}
return ['USD', 'EUR'];
return getCurrencyPreferences(countryCode).filter(
(currency) => currency === 'USD' || currency === 'EUR' || GIFT_ELIGIBLE_LOCALIZED_CURRENCIES.has(currency),
);
}
@@ -55,11 +55,11 @@ describe('getCurrency', () => {
it('returns EUR for Finland', () => {
expect(getCurrency('FI')).toBe('EUR');
});
it('returns EUR for Sweden', () => {
expect(getCurrency('SE')).toBe('EUR');
it('returns SEK for Sweden', () => {
expect(getCurrency('SE')).toBe('SEK');
});
it('returns EUR for Denmark', () => {
expect(getCurrency('DK')).toBe('EUR');
it('returns DKK for Denmark', () => {
expect(getCurrency('DK')).toBe('DKK');
});
it('returns PLN for Poland', () => {
expect(getCurrency('PL')).toBe('PLN');
@@ -76,8 +76,8 @@ describe('getCurrency', () => {
it('returns EUR for Romania', () => {
expect(getCurrency('RO')).toBe('EUR');
});
it('returns EUR for Norway (EEA but not EU)', () => {
expect(getCurrency('NO')).toBe('EUR');
it('returns NOK for Norway (EEA but not EU)', () => {
expect(getCurrency('NO')).toBe('NOK');
});
it('returns EUR for Iceland (EEA but not EU)', () => {
expect(getCurrency('IS')).toBe('EUR');
@@ -128,7 +128,6 @@ describe('getCurrency', () => {
'HR',
'CY',
'CZ',
'DK',
'EE',
'FI',
'FR',
@@ -147,10 +146,8 @@ describe('getCurrency', () => {
'SK',
'SI',
'ES',
'SE',
'IS',
'LI',
'NO',
];
for (const country of eeaCountries) {
it(`returns EUR for ${country}`, () => {
@@ -160,16 +157,30 @@ describe('getCurrency', () => {
it('uses local currency for Poland', () => {
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', () => {
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']) {
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('PL')).toEqual(['EUR', 'USD']);
});
@@ -184,7 +195,7 @@ describe('getGiftCurrencyPreferences', () => {
expect(getGiftCurrencyPreferences(undefined)).toEqual(['USD', 'EUR']);
});
it('is case insensitive', () => {
expect(getGiftCurrencyPreferences('de')).toEqual(['EUR', 'USD']);
expect(getGiftCurrencyPreferences('se')).toEqual(['SEK', 'EUR', 'USD']);
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/risk/__tests__/AccountPolicyService.test.ts',
'src/api/stripe/tests/StripeCheckoutCountryEnforcement.test.ts',
'src/api/stripe/tests/StripeNordicCurrencies.test.ts',
];
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 |
| EUR | Euro |
| BRL | Brazilian real |
| DKK | Danish krone |
| INR | Indian rupee |
| NOK | Norwegian krone |
| PLN | Polish zloty |
| SEK | Swedish krona |
| TRY | Turkish lira |
## 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.
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`
@@ -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_EUR: {path: ['integrations', 'stripe', 'prices', 'monthly_eur']},
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_NOK: {path: ['integrations', 'stripe', 'prices', 'monthly_nok']},
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_YEARLY_USD: {path: ['integrations', 'stripe', 'prices', 'yearly_usd']},
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_DKK: {path: ['integrations', 'stripe', 'prices', 'yearly_dkk']},
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_SEK: {path: ['integrations', 'stripe', 'prices', 'yearly_sek']},
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_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_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_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_INR: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_inr']},
FLUXER_STRIPE_PRICE_GIFT_1_MONTH_PLN: {path: ['integrations', 'stripe', 'prices', 'gift_1_month_pln']},
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ar\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: bg\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: cs\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: da\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: de\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: el\n"
"MIME-Version: 1.0\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 ""
"Αν γράφεις για το {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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: en-GB\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: en-US\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: es-419\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: es-ES\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: fi\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: fr\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: he\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: hi\n"
"MIME-Version: 1.0\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 ""
"अगर आप {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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: hr\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: hu\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: id\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: it\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ja\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ko\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: lt\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: nl\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: no\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: pl\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: pt-BR\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ro\n"
"MIME-Version: 1.0\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 ""
"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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: ru\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: sv-SE\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: th\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: tr\n"
"MIME-Version: 1.0\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 ""
"{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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: uk\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -10
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: vi\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: zh-CN\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
+2 -9
View File
@@ -4,8 +4,8 @@
msgid ""
msgstr ""
"Project-Id-Version: fluxer-marketing\n"
"POT-Creation-Date: 2026-09-10 00:00+0000\n"
"PO-Revision-Date: 2026-09-10 00:00+0000\n"
"POT-Creation-Date: 2026-09-11 00:00+0000\n"
"PO-Revision-Date: 2026-09-11 00:00+0000\n"
"Language: zh-TW\n"
"MIME-Version: 1.0\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."
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.
#: fluxer_marketing/generated:pricing_and_tiers.billing.monthly_price
msgctxt "pricing_and_tiers.billing.monthly_price"
@@ -29,8 +29,10 @@ export const PriceIdsResponse = z.object({
.nullish()
.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'),
currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency for the prices'),
gift_currency: z.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY']).describe('Currency for gift 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', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.describe('Currency for gift prices'),
});
export type PriceIdsResponse = z.infer<typeof PriceIdsResponse>;
@@ -83,7 +85,9 @@ export const CurrentSubscriptionPriceResponse = z
.object({
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'),
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'),
is_grandfathered: z
.boolean()
@@ -119,7 +123,10 @@ export const PendingSubscriptionChangeResponse = z
.int()
.nullable()
.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
.number()
.int()
@@ -187,7 +194,7 @@ export const ListPriceSwitchState = z.object({
.nullable()
.describe('Current list price for the same cycle and currency, in the currency minor unit'),
currency: z
.enum(['USD', 'EUR', 'BRL', 'INR', 'PLN', 'TRY'])
.enum(['USD', 'EUR', 'BRL', 'DKK', 'INR', 'NOK', 'PLN', 'SEK', 'TRY'])
.nullable()
.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'),
@@ -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_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'),
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({
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_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'),
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({
status: z.literal('ineligible').describe('The subscription cannot be moved to the current list price'),