Refactored i18n configuration, replacing `DEFAULT_LOCALE` with `DEFAULT_LOCALE_FALLBACK` and enhancing environment-based locale validation. Improved cookie persistence for cart and wishlist, ensuring fallback handling for unauthenticated users. Enhancements: - Added `createProjectKey` utility for consistent project key generation. - Reworked cart and wishlist composables (`useOrderOverwrite`, `useWishlistOverwrite`) to decouple product identifier and handle cookies robustly. - Centralized `DEFAULT_LOCALE` logic for better maintainability. - Refined `useOrderSync` and `useWishlistSync` for clean synchronization across auth states. - Updated SCSS in hero and header styles for alignment corrections. Breaking Changes: `DEFAULT_LOCALE` constant removed; replaced with runtime config and fallback logic. Consumers must adapt to `DEFAULT_LOCALE_FALLBACK` and `$appHelpers.DEFAULT_LOCALE`.
99 lines
No EOL
4.6 KiB
TypeScript
99 lines
No EOL
4.6 KiB
TypeScript
|
||
export function transliterate(str: string | undefined): string {
|
||
if (!str) return '';
|
||
|
||
const map = {
|
||
// Russian/Ukrainian/Belarusian Cyrillic
|
||
'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'Yo', 'Ж': 'Zh',
|
||
'З': 'Z', 'И': 'I', 'Й': 'Y', 'К': 'K', 'Л': 'L', 'М': 'M', 'Н': 'N', 'О': 'O',
|
||
'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U', 'Ф': 'F', 'Х': 'Kh', 'Ц': 'Ts',
|
||
'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Shch', 'Ъ': '', 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu',
|
||
'Я': 'Ya',
|
||
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh',
|
||
'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o',
|
||
'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', 'ф': 'f', 'х': 'kh', 'ц': 'ts',
|
||
'ч': 'ch', 'ш': 'sh', 'щ': 'shch', 'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu',
|
||
'я': 'ya',
|
||
|
||
// Ukrainian extras
|
||
'Ґ': 'G', 'ґ': 'g', 'Є': 'Ye', 'є': 'ye', 'І': 'I', 'і': 'i', 'Ї': 'Yi', 'ї': 'yi',
|
||
|
||
// Serbian/Macedonian Cyrillic extras
|
||
'Ђ': 'Dj', 'ђ': 'dj', 'Ј': 'J', 'ј': 'j', 'Љ': 'Lj', 'љ': 'lj', 'Њ': 'Nj', 'њ': 'nj',
|
||
'Ћ': 'C', 'ћ': 'c', 'Џ': 'Dz', 'џ': 'dz', 'Ѓ': 'Gj', 'ѓ': 'gj', 'Ѕ': 'Dz', 'ѕ': 'dz',
|
||
'Ќ': 'Kj', 'ќ': 'kj',
|
||
|
||
// Belarusian extras
|
||
'Ў': 'U', 'ў': 'u',
|
||
|
||
// Bulgarian extras (mostly covered above, but ъ is different)
|
||
// In Bulgarian context ъ = 'a', but we keep '' as default for Russian
|
||
|
||
// Greek
|
||
'Α': 'A', 'Β': 'V', 'Γ': 'G', 'Δ': 'D', 'Ε': 'E', 'Ζ': 'Z', 'Η': 'I', 'Θ': 'Th',
|
||
'Ι': 'I', 'Κ': 'K', 'Λ': 'L', 'Μ': 'M', 'Ν': 'N', 'Ξ': 'X', 'Ο': 'O', 'Π': 'P',
|
||
'Ρ': 'R', 'Σ': 'S', 'Τ': 'T', 'Υ': 'Y', 'Φ': 'F', 'Χ': 'Ch', 'Ψ': 'Ps', 'Ω': 'O',
|
||
'α': 'a', 'β': 'v', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'i', 'θ': 'th',
|
||
'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': 'x', 'ο': 'o', 'π': 'p',
|
||
'ρ': 'r', 'σ': 's', 'ς': 's', 'τ': 't', 'υ': 'y', 'φ': 'f', 'χ': 'ch', 'ψ': 'ps', 'ω': 'o',
|
||
|
||
// Arabic
|
||
'ا': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'j', 'ح': 'h', 'خ': 'kh', 'د': 'd',
|
||
'ذ': 'dh', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't',
|
||
'ظ': 'z', 'ع': 'a', 'غ': 'gh', 'ف': 'f', 'ق': 'q', 'ك': 'k', 'ل': 'l', 'م': 'm',
|
||
'ن': 'n', 'ه': 'h', 'و': 'w', 'ي': 'y', 'ة': 'h', 'ء': '\'', 'آ': 'aa',
|
||
|
||
// German/Nordic/Central European diacritics
|
||
'Ä': 'Ae', 'ä': 'ae', 'Ö': 'Oe', 'ö': 'oe', 'Ü': 'Ue', 'ü': 'ue', 'ß': 'ss',
|
||
'Å': 'A', 'å': 'a', 'Æ': 'Ae', 'æ': 'ae', 'Ø': 'O', 'ø': 'o',
|
||
'Ð': 'D', 'ð': 'd', 'Þ': 'Th', 'þ': 'th',
|
||
|
||
// Czech/Slovak/Polish/Hungarian/Romanian/Turkish
|
||
'Č': 'C', 'č': 'c', 'Ď': 'D', 'ď': 'd', 'Ě': 'E', 'ě': 'e', 'Ň': 'N', 'ň': 'n',
|
||
'Ř': 'R', 'ř': 'r', 'Š': 'S', 'š': 's', 'Ť': 'T', 'ť': 't', 'Ů': 'U', 'ů': 'u',
|
||
'Ž': 'Z', 'ž': 'z', 'Ľ': 'L', 'ľ': 'l', 'Ĺ': 'L', 'ĺ': 'l', 'Ŕ': 'R', 'ŕ': 'r',
|
||
'Ą': 'A', 'ą': 'a', 'Ć': 'C', 'ć': 'c', 'Ę': 'E', 'ę': 'e', 'Ł': 'L', 'ł': 'l',
|
||
'Ń': 'N', 'ń': 'n', 'Ś': 'S', 'ś': 's', 'Ź': 'Z', 'ź': 'z', 'Ż': 'Z', 'ż': 'z',
|
||
'Á': 'A', 'á': 'a', 'É': 'E', 'é': 'e', 'Í': 'I', 'í': 'i', 'Ó': 'O', 'ó': 'o',
|
||
'Ú': 'U', 'ú': 'u', 'Ý': 'Y', 'ý': 'y',
|
||
'Ő': 'O', 'ő': 'o', 'Ű': 'U', 'ű': 'u',
|
||
'Ă': 'A', 'ă': 'a', 'Â': 'A', 'â': 'a', 'Î': 'I', 'î': 'i', 'Ș': 'S', 'ș': 's', 'Ț': 'T', 'ț': 't',
|
||
'Ç': 'C', 'ç': 'c', 'Ğ': 'G', 'ğ': 'g', 'İ': 'I', 'ı': 'i', 'Ş': 'S', 'ş': 's',
|
||
|
||
// Vietnamese (basic - stripped of tone marks conceptually)
|
||
'Đ': 'D', 'đ': 'd',
|
||
|
||
// Spanish/Portuguese/French
|
||
'Ñ': 'N', 'ñ': 'n',
|
||
'À': 'A', 'à': 'a', 'È': 'E', 'è': 'e', 'Ì': 'I', 'ì': 'i', 'Ò': 'O', 'ò': 'o',
|
||
'Ù': 'U', 'ù': 'u', 'Ë': 'E', 'ë': 'e', 'Ï': 'I', 'ï': 'i',
|
||
'Ê': 'E', 'ê': 'e', 'Ô': 'O', 'ô': 'o', 'Û': 'U', 'û': 'u',
|
||
'Ã': 'A', 'ã': 'a', 'Õ': 'O', 'õ': 'o',
|
||
};
|
||
|
||
return str.split('').map(ch => {
|
||
if (ch in map) return map[ch];
|
||
|
||
const normalized = ch
|
||
.normalize('NFD')
|
||
.replace(/[\u0300-\u036f]/g, '');
|
||
|
||
if (normalized !== ch && /^[\x20-\x7E]+$/.test(normalized)) {
|
||
return normalized;
|
||
}
|
||
|
||
return ch;
|
||
}).join('');
|
||
}
|
||
|
||
export function createProjectKey(str: string | undefined): string {
|
||
if (!str) return 'default-project';
|
||
|
||
return transliterate(str)
|
||
.toLowerCase()
|
||
.replace(/['"]/g, '')
|
||
.replace(/[^a-z0-9\s-]/g, '')
|
||
.trim()
|
||
.replace(/\s+/g, '-')
|
||
.replace(/-+/g, '-');
|
||
} |