Files
boc/landvex-quixzoom-cms/src/config/sites.ts
T
Bernt 6989a98d75 feat: Passwordless cross-device authentication
- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
2026-07-07 07:11:50 +00:00

646 lines
21 KiB
TypeScript

/**
* Global site configuration for Landvex/QuiXzoom content network
* Defines all brands, tiers, languages, and regional settings
*/
export type SiteTier = 'global' | 'national' | 'regional';
export type ContentStatus = 'current' | 'outdated' | 'pending_review' | 'approved' | 'published';
export type ReviewStatus = 'ai_translated' | 'human_reviewed' | 'locally_adapted' | 'regional_approved';
export interface LanguageConfig {
code: string; // ISO 639-1 + region: en-US, sv-SE, de-DE
name: string; // Display name
nativeName: string; // Name in native language
direction: 'ltr' | 'rtl';
currency: string; // Default currency for this locale
dateFormat: string;
numberFormat: string;
seoLocale: string; // hreflang value
}
export interface SiteConfig {
domain: string;
brand: 'landvex' | 'quixzoom';
tier: SiteTier;
languages: LanguageConfig[];
defaultLanguage: string;
region?: string; // For regional hubs
countries?: string[]; // Countries covered
features: {
ecommerce: boolean;
blog: boolean;
faq: boolean;
cases: boolean;
docs: boolean;
contact: boolean;
};
contacts: {
supportEmail?: string;
salesEmail?: string;
phone?: string;
address?: string;
};
legal: {
companyName: string;
vatNumber?: string;
registrationNumber?: string;
jurisdiction: string;
};
}
// === GLOBAL SOURCE OF TRUTH (Tier 1) ===
export const GLOBAL_SITES: SiteConfig[] = [
{
domain: 'landvex.com',
brand: 'landvex',
tier: 'global',
languages: [{
code: 'en-US',
name: 'English (US)',
nativeName: 'English',
direction: 'ltr',
currency: 'USD',
dateFormat: 'MM/DD/YYYY',
numberFormat: 'en-US',
seoLocale: 'en-US'
}],
defaultLanguage: 'en-US',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@landvex.com',
salesEmail: 'sales@landvex.com',
phone: '+1-800-LANDVEX'
},
legal: {
companyName: 'Landvex Inc.',
vatNumber: null as any,
registrationNumber: 'DE123456789',
jurisdiction: 'Delaware, USA'
}
},
{
domain: 'quixzoom.com',
brand: 'quixzoom',
tier: 'global',
languages: [{
code: 'en-US',
name: 'English (US)',
nativeName: 'English',
direction: 'ltr',
currency: 'USD',
dateFormat: 'MM/DD/YYYY',
numberFormat: 'en-US',
seoLocale: 'en-US'
}],
defaultLanguage: 'en-US',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@quixzoom.com',
salesEmail: 'sales@quixzoom.com',
phone: '+1-800-QUIXZOOM'
},
legal: {
companyName: 'QuiXzoom Inc.',
vatNumber: null as any,
registrationNumber: 'DE987654321',
jurisdiction: 'Delaware, USA'
}
}
];
// === NATIONAL SITES (Tier 2) ===
export const NATIONAL_SITES: SiteConfig[] = [
// Sweden
{
domain: 'quixzoom.se',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'sv-SE',
name: 'Swedish',
nativeName: 'Svenska',
direction: 'ltr',
currency: 'SEK',
dateFormat: 'YYYY-MM-DD',
numberFormat: 'sv-SE',
seoLocale: 'sv-SE'
}],
defaultLanguage: 'sv-SE',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@quixzoom.se',
salesEmail: 'sales@quixzoom.se',
phone: '+46-8-123-456-78',
address: 'Stureplan 4C, 114 35 Stockholm'
},
legal: {
companyName: 'QuiXzoom Nordic AB',
vatNumber: 'SE556123456701',
registrationNumber: '556123-4567',
jurisdiction: 'Sweden'
}
},
{
domain: 'landvex.se',
brand: 'landvex',
tier: 'national',
languages: [{
code: 'sv-SE',
name: 'Swedish',
nativeName: 'Svenska',
direction: 'ltr',
currency: 'SEK',
dateFormat: 'YYYY-MM-DD',
numberFormat: 'sv-SE',
seoLocale: 'sv-SE'
}],
defaultLanguage: 'sv-SE',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@landvex.se',
salesEmail: 'sales@landvex.se',
phone: '+46-8-987-654-32',
address: 'Kungsgatan 37, 111 56 Stockholm'
},
legal: {
companyName: 'Landvex Nordic AB',
vatNumber: 'SE556987654301',
registrationNumber: '556987-6543',
jurisdiction: 'Sweden'
}
},
// Germany
{
domain: 'quixzoom.de',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'de-DE',
name: 'German',
nativeName: 'Deutsch',
direction: 'ltr',
currency: 'EUR',
dateFormat: 'DD.MM.YYYY',
numberFormat: 'de-DE',
seoLocale: 'de-DE'
}],
defaultLanguage: 'de-DE',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@quixzoom.de',
salesEmail: 'vertrieb@quixzoom.de',
phone: '+49-30-12345678',
address: 'Friedrichstraße 171, 10117 Berlin'
},
legal: {
companyName: 'QuiXzoom GmbH',
vatNumber: 'DE123456789',
registrationNumber: 'HRB 123456 B',
jurisdiction: 'Germany'
}
},
// Netherlands
{
domain: 'quixzoom.nl',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'nl-NL',
name: 'Dutch',
nativeName: 'Nederlands',
direction: 'ltr',
currency: 'EUR',
dateFormat: 'DD-MM-YYYY',
numberFormat: 'nl-NL',
seoLocale: 'nl-NL'
}],
defaultLanguage: 'nl-NL',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@quixzoom.nl',
salesEmail: 'verkoop@quixzoom.nl',
phone: '+31-20-123-4567',
address: 'Herengracht 420, 1017 BZ Amsterdam'
},
legal: {
companyName: 'QuiXzoom B.V.',
vatNumber: 'NL123456789B01',
registrationNumber: '12345678',
jurisdiction: 'Netherlands'
}
},
// France
{
domain: 'quixzoom.fr',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'fr-FR',
name: 'French',
nativeName: 'Français',
direction: 'ltr',
currency: 'EUR',
dateFormat: 'DD/MM/YYYY',
numberFormat: 'fr-FR',
seoLocale: 'fr-FR'
}],
defaultLanguage: 'fr-FR',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@quixzoom.fr',
salesEmail: 'ventes@quixzoom.fr',
phone: '+33-1-23-45-67-89',
address: '25 Rue de la Paix, 75002 Paris'
},
legal: {
companyName: 'QuiXzoom SARL',
vatNumber: 'FR12345678901',
registrationNumber: '123 456 789 RCS Paris',
jurisdiction: 'France'
}
},
// Spain
{
domain: 'quixzoom.es',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'es-ES',
name: 'Spanish',
nativeName: 'Español',
direction: 'ltr',
currency: 'EUR',
dateFormat: 'DD/MM/YYYY',
numberFormat: 'es-ES',
seoLocale: 'es-ES'
}],
defaultLanguage: 'es-ES',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'soporte@quixzoom.es',
salesEmail: 'ventas@quixzoom.es',
phone: '+34-91-123-4567',
address: 'Calle de Alcalá 45, 28014 Madrid'
},
legal: {
companyName: 'QuiXzoom SL',
vatNumber: 'ESB12345678',
registrationNumber: 'B-12345678',
jurisdiction: 'Spain'
}
},
// Italy
{
domain: 'quixzoom.it',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'it-IT',
name: 'Italian',
nativeName: 'Italiano',
direction: 'ltr',
currency: 'EUR',
dateFormat: 'DD/MM/YYYY',
numberFormat: 'it-IT',
seoLocale: 'it-IT'
}],
defaultLanguage: 'it-IT',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'supporto@quixzoom.it',
salesEmail: 'vendite@quixzoom.it',
phone: '+39-02-1234-5678',
address: 'Via Monte Napoleone 8, 20121 Milano'
},
legal: {
companyName: 'QuiXzoom SRL',
vatNumber: 'IT12345678901',
registrationNumber: 'MI-1234567',
jurisdiction: 'Italy'
}
},
// Poland
{
domain: 'quixzoom.pl',
brand: 'quixzoom',
tier: 'national',
languages: [{
code: 'pl-PL',
name: 'Polish',
nativeName: 'Polski',
direction: 'ltr',
currency: 'PLN',
dateFormat: 'DD.MM.YYYY',
numberFormat: 'pl-PL',
seoLocale: 'pl-PL'
}],
defaultLanguage: 'pl-PL',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'pomoc@quixzoom.pl',
salesEmail: 'sprzedaz@quixzoom.pl',
phone: '+48-22-123-4567',
address: 'ul. Marszałkowska 100, 00-017 Warszawa'
},
legal: {
companyName: 'QuiXzoom Sp. z o.o.',
vatNumber: 'PL1234567890',
registrationNumber: '0000123456',
jurisdiction: 'Poland'
}
}
];
// === REGIONAL HUBS (Tier 3) ===
export const REGIONAL_SITES: SiteConfig[] = [
{
domain: 'quixzoom.asia',
brand: 'quixzoom',
tier: 'regional',
region: 'asia-pacific',
countries: ['CN', 'JP', 'KR', 'TH', 'VN', 'ID', 'MY', 'IN', 'SG', 'TW', 'HK'],
languages: [
{ code: 'zh-CN', name: 'Chinese (Simplified)', nativeName: '简体中文', direction: 'ltr', currency: 'CNY', dateFormat: 'YYYY-MM-DD', numberFormat: 'zh-CN', seoLocale: 'zh-CN' },
{ code: 'zh-TW', name: 'Chinese (Traditional)', nativeName: '繁體中文', direction: 'ltr', currency: 'TWD', dateFormat: 'YYYY-MM-DD', numberFormat: 'zh-TW', seoLocale: 'zh-TW' },
{ code: 'ja-JP', name: 'Japanese', nativeName: '日本語', direction: 'ltr', currency: 'JPY', dateFormat: 'YYYY/MM/DD', numberFormat: 'ja-JP', seoLocale: 'ja-JP' },
{ code: 'ko-KR', name: 'Korean', nativeName: '한국어', direction: 'ltr', currency: 'KRW', dateFormat: 'YYYY.MM.DD', numberFormat: 'ko-KR', seoLocale: 'ko-KR' },
{ code: 'th-TH', name: 'Thai', nativeName: 'ไทย', direction: 'ltr', currency: 'THB', dateFormat: 'DD/MM/YYYY', numberFormat: 'th-TH', seoLocale: 'th-TH' },
{ code: 'vi-VN', name: 'Vietnamese', nativeName: 'Tiếng Việt', direction: 'ltr', currency: 'VND', dateFormat: 'DD/MM/YYYY', numberFormat: 'vi-VN', seoLocale: 'vi-VN' },
{ code: 'id-ID', name: 'Indonesian', nativeName: 'Bahasa Indonesia', direction: 'ltr', currency: 'IDR', dateFormat: 'DD/MM/YYYY', numberFormat: 'id-ID', seoLocale: 'id-ID' },
{ code: 'ms-MY', name: 'Malay', nativeName: 'Bahasa Melayu', direction: 'ltr', currency: 'MYR', dateFormat: 'DD/MM/YYYY', numberFormat: 'ms-MY', seoLocale: 'ms-MY' },
{ code: 'hi-IN', name: 'Hindi', nativeName: 'हिन्दी', direction: 'ltr', currency: 'INR', dateFormat: 'DD/MM/YYYY', numberFormat: 'hi-IN', seoLocale: 'hi-IN' }
],
defaultLanguage: 'en-US',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@quixzoom.asia',
salesEmail: 'sales@quixzoom.asia',
phone: '+65-6123-4567',
address: '1 Raffles Place, #25-01, Singapore 048616'
},
legal: {
companyName: 'QuiXzoom Asia Pacific Pte. Ltd.',
vatNumber: null as any,
registrationNumber: '202312345K',
jurisdiction: 'Singapore'
}
},
{
domain: 'landvex.asia',
brand: 'landvex',
tier: 'regional',
region: 'asia-pacific',
countries: ['CN', 'JP', 'KR', 'TH', 'VN', 'ID', 'MY', 'IN', 'SG', 'TW', 'HK'],
languages: [
{ code: 'zh-CN', name: 'Chinese (Simplified)', nativeName: '简体中文', direction: 'ltr', currency: 'CNY', dateFormat: 'YYYY-MM-DD', numberFormat: 'zh-CN', seoLocale: 'zh-CN' },
{ code: 'zh-TW', name: 'Chinese (Traditional)', nativeName: '繁體中文', direction: 'ltr', currency: 'TWD', dateFormat: 'YYYY-MM-DD', numberFormat: 'zh-TW', seoLocale: 'zh-TW' },
{ code: 'ja-JP', name: 'Japanese', nativeName: '日本語', direction: 'ltr', currency: 'JPY', dateFormat: 'YYYY/MM/DD', numberFormat: 'ja-JP', seoLocale: 'ja-JP' },
{ code: 'ko-KR', name: 'Korean', nativeName: '한국어', direction: 'ltr', currency: 'KRW', dateFormat: 'YYYY.MM.DD', numberFormat: 'ko-KR', seoLocale: 'ko-KR' },
{ code: 'th-TH', name: 'Thai', nativeName: 'ไทย', direction: 'ltr', currency: 'THB', dateFormat: 'DD/MM/YYYY', numberFormat: 'th-TH', seoLocale: 'th-TH' },
{ code: 'vi-VN', name: 'Vietnamese', nativeName: 'Tiếng Việt', direction: 'ltr', currency: 'VND', dateFormat: 'DD/MM/YYYY', numberFormat: 'vi-VN', seoLocale: 'vi-VN' },
{ code: 'id-ID', name: 'Indonesian', nativeName: 'Bahasa Indonesia', direction: 'ltr', currency: 'IDR', dateFormat: 'DD/MM/YYYY', numberFormat: 'id-ID', seoLocale: 'id-ID' },
{ code: 'ms-MY', name: 'Malay', nativeName: 'Bahasa Melayu', direction: 'ltr', currency: 'MYR', dateFormat: 'DD/MM/YYYY', numberFormat: 'ms-MY', seoLocale: 'ms-MY' },
{ code: 'hi-IN', name: 'Hindi', nativeName: 'हिन्दी', direction: 'ltr', currency: 'INR', dateFormat: 'DD/MM/YYYY', numberFormat: 'hi-IN', seoLocale: 'hi-IN' }
],
defaultLanguage: 'en-US',
features: {
ecommerce: true,
blog: true,
faq: true,
cases: true,
docs: true,
contact: true
},
contacts: {
supportEmail: 'support@landvex.asia',
salesEmail: 'sales@landvex.asia',
phone: '+65-6987-6543',
address: 'Marina Bay Financial Centre, Tower 3, #15-01, Singapore 018982'
},
legal: {
companyName: 'Landvex Asia Pacific Pte. Ltd.',
vatNumber: null as any,
registrationNumber: '202398765K',
jurisdiction: 'Singapore'
}
}
];
// All sites combined
export const ALL_SITES: SiteConfig[] = [...GLOBAL_SITES, ...NATIONAL_SITES, ...REGIONAL_SITES];
// Helper functions
export function getSiteByDomain(domain: string): SiteConfig | undefined {
return ALL_SITES.find(s => s.domain === domain);
}
export function getSitesByBrand(brand: 'landvex' | 'quixzoom'): SiteConfig[] {
return ALL_SITES.filter(s => s.brand === brand);
}
export function getSitesByTier(tier: SiteTier): SiteConfig[] {
return ALL_SITES.filter(s => s.tier === tier);
}
export function getGlobalSource(brand: 'landvex' | 'quixzoom'): SiteConfig {
return ALL_SITES.find(s => s.tier === 'global' && s.brand === brand)!;
}
export function getLanguageConfig(site: SiteConfig, langCode: string): LanguageConfig | undefined {
return site.languages.find(l => l.code === langCode);
}
// Supported target languages for translation (all non-English)
export const TRANSLATION_TARGETS = [
'sv-SE', 'de-DE', 'nl-NL', 'fr-FR', 'es-ES', 'it-IT', 'pl-PL',
'zh-CN', 'zh-TW', 'ja-JP', 'ko-KR', 'th-TH', 'vi-VN', 'id-ID', 'ms-MY', 'hi-IN'
];
// Language-specific transcreation prompts
export const TRANSCREATION_PROMPTS: Record<string, string> = {
'sv-SE': `You are a Swedish transcreation expert. Adapt the content for Swedish audience:
- Use informal "du" (not formal "ni") for B2C, "ni" for formal B2B
- Reference Swedish regulations (GDPR, Swedish Consumer Agency)
- Use Swedish cultural references when appropriate
- Adapt examples to Swedish context (Stockholm, Gothenburg, Malmö)
- Currency: SEK, date format: YYYY-MM-DD`,
'de-DE': `You are a German transcreation expert. Adapt the content for German audience:
- Use formal "Sie" for business context
- Reference German regulations (BDSG, DSGVO)
- Be thorough and detailed — Germans expect completeness
- Adapt examples to German cities (Berlin, Munich, Hamburg)
- Currency: EUR, date format: DD.MM.YYYY`,
'nl-NL': `You are a Dutch transcreation expert. Adapt the content for Dutch audience:
- Use informal "je" for most contexts
- Reference Dutch regulations (AVG, ACM)
- Be direct and concise — Dutch appreciate straightforwardness
- Adapt examples to Dutch context (Amsterdam, Rotterdam, The Hague)
- Currency: EUR, date format: DD-MM-YYYY`,
'fr-FR': `You are a French transcreation expert. Adapt the content for French audience:
- Use formal "vous" for business
- Reference French regulations (RGPD, DGCCRF)
- Be elegant but clear — French appreciate quality expression
- Adapt examples to French context (Paris, Lyon, Marseille)
- Currency: EUR, date format: DD/MM/YYYY`,
'es-ES': `You are a Spanish transcreation expert. Adapt the content for Spanish audience:
- Use formal "usted" for business, "tú" for casual
- Reference Spanish regulations (LOPD, AEPD)
- Be warm and relationship-oriented
- Adapt examples to Spanish context (Madrid, Barcelona, Valencia)
- Currency: EUR, date format: DD/MM/YYYY`,
'it-IT': `You are an Italian transcreation expert. Adapt the content for Italian audience:
- Use formal "Lei" for business
- Reference Italian regulations (GDPR-IT, AGCM)
- Be expressive and passionate when appropriate
- Adapt examples to Italian context (Milan, Rome, Turin)
- Currency: EUR, date format: DD/MM/YYYY`,
'pl-PL': `You are a Polish transcreation expert. Adapt the content for Polish audience:
- Use formal "Pan/Pani" for business
- Reference Polish regulations (RODO, UOKiK)
- Be detailed and factual
- Adapt examples to Polish context (Warsaw, Kraków, Wrocław)
- Currency: PLN, date format: DD.MM.YYYY`,
'zh-CN': `You are a Chinese (Simplified) transcreation expert. Adapt for mainland China:
- Reference Chinese regulations (PRC Cybersecurity Law, PIPL)
- Use Simplified Chinese characters (简体中文)
- Be respectful and formal in business context
- Adapt examples to Chinese cities (Beijing, Shanghai, Shenzhen)
- Currency: CNY (RMB), date format: YYYY-MM-DD`,
'zh-TW': `You are a Chinese (Traditional) transcreation expert. Adapt for Taiwan:
- Reference Taiwanese regulations (PDPA Taiwan)
- Use Traditional Chinese characters (繁體中文)
- Be polite and formal in business
- Adapt examples to Taiwanese context (Taipei, Kaohsiung, Taichung)
- Currency: TWD, date format: YYYY-MM-DD`,
'ja-JP': `You are a Japanese transcreation expert. Adapt for Japanese audience:
- Use keigo (polite language) for business
- Reference Japanese regulations (APPI, Consumer Contract Act)
- Be extremely polite and indirect
- Adapt examples to Japanese context (Tokyo, Osaka, Kyoto)
- Currency: JPY, date format: YYYY/MM/DD`,
'ko-KR': `You are a Korean transcreation expert. Adapt for Korean audience:
- Use formal speech (존칭) for business
- Reference Korean regulations (PIPA, KCC)
- Be respectful and hierarchical
- Adapt examples to Korean context (Seoul, Busan, Incheon)
- Currency: KRW, date format: YYYY.MM.DD`,
'th-TH': `You are a Thai transcreation expert. Adapt for Thai audience:
- Be respectful and use polite particles
- Reference Thai regulations (PDPA Thailand)
- Build relationship first, business second
- Adapt examples to Thai context (Bangkok, Chiang Mai, Phuket)
- Currency: THB, date format: DD/MM/YYYY`,
'vi-VN': `You are a Vietnamese transcreation expert. Adapt for Vietnamese audience:
- Be respectful but warm
- Reference Vietnamese regulations (Cybersecurity Law, Decree 13)
- Adapt examples to Vietnamese context (Ho Chi Minh City, Hanoi, Da Nang)
- Currency: VND, date format: DD/MM/YYYY`,
'id-ID': `You are an Indonesian transcreation expert. Adapt for Indonesian audience:
- Be friendly and approachable
- Reference Indonesian regulations (PDP Law, ITE Law)
- Adapt examples to Indonesian context (Jakarta, Surabaya, Bandung)
- Currency: IDR, date format: DD/MM/YYYY`,
'ms-MY': `You are a Malay transcreation expert. Adapt for Malaysian audience:
- Be respectful and inclusive (multicultural context)
- Reference Malaysian regulations (PDPA Malaysia)
- Adapt examples to Malaysian context (Kuala Lumpur, Penang, Johor)
- Currency: MYR, date format: DD/MM/YYYY`,
'hi-IN': `You are a Hindi transcreation expert. Adapt for Indian audience:
- Mix Hindi and English (Hinglish) is common for tech
- Reference Indian regulations (DPDP Act 2023, IT Act)
- Adapt examples to Indian context (Mumbai, Delhi, Bangalore)
- Currency: INR, date format: DD/MM/YYYY`
};