style: auto-format codebase with Prettier

Applied formatting to 1487+ files using pnpm format:write
  - TypeScript/JavaScript files
  - Svelte components
  - Astro pages
  - JSON configs
  - Markdown docs

  13 files still need manual review (Astro JSX comments)
This commit is contained in:
Wuesteon 2025-11-27 18:33:16 +01:00
parent 0241f5554c
commit d36b321d9d
3952 changed files with 661498 additions and 739751 deletions

View file

@ -9,71 +9,71 @@ import { type LanguageCode, isLanguageSupported } from './languages';
* Works in browser environment only
*/
export function detectBrowserLocale(
supportedLocales: readonly string[],
defaultLocale: string = 'en'
supportedLocales: readonly string[],
defaultLocale: string = 'en'
): string {
if (typeof navigator === 'undefined') {
return defaultLocale;
}
if (typeof navigator === 'undefined') {
return defaultLocale;
}
// Try navigator.language first
const browserLang = navigator.language;
// Try navigator.language first
const browserLang = navigator.language;
// Check exact match (e.g., 'pt-BR')
if (supportedLocales.includes(browserLang)) {
return browserLang;
}
// Check exact match (e.g., 'pt-BR')
if (supportedLocales.includes(browserLang)) {
return browserLang;
}
// Check base language (e.g., 'pt' from 'pt-BR')
const baseLang = browserLang.split('-')[0];
if (supportedLocales.includes(baseLang)) {
return baseLang;
}
// Check base language (e.g., 'pt' from 'pt-BR')
const baseLang = browserLang.split('-')[0];
if (supportedLocales.includes(baseLang)) {
return baseLang;
}
// Try navigator.languages array
if (navigator.languages) {
for (const lang of navigator.languages) {
if (supportedLocales.includes(lang)) {
return lang;
}
const base = lang.split('-')[0];
if (supportedLocales.includes(base)) {
return base;
}
}
}
// Try navigator.languages array
if (navigator.languages) {
for (const lang of navigator.languages) {
if (supportedLocales.includes(lang)) {
return lang;
}
const base = lang.split('-')[0];
if (supportedLocales.includes(base)) {
return base;
}
}
}
return defaultLocale;
return defaultLocale;
}
/**
* Get locale from localStorage with validation
*/
export function getStoredLocale(
storageKey: string,
supportedLocales: readonly string[]
storageKey: string,
supportedLocales: readonly string[]
): string | null {
if (typeof localStorage === 'undefined') {
return null;
}
if (typeof localStorage === 'undefined') {
return null;
}
const stored = localStorage.getItem(storageKey);
if (stored && supportedLocales.includes(stored)) {
return stored;
}
const stored = localStorage.getItem(storageKey);
if (stored && supportedLocales.includes(stored)) {
return stored;
}
return null;
return null;
}
/**
* Store locale in localStorage
*/
export function storeLocale(storageKey: string, locale: string): void {
if (typeof localStorage === 'undefined') {
return;
}
if (typeof localStorage === 'undefined') {
return;
}
localStorage.setItem(storageKey, locale);
localStorage.setItem(storageKey, locale);
}
/**
@ -83,18 +83,18 @@ export function storeLocale(storageKey: string, locale: string): void {
* 3. Default locale
*/
export function getInitialLocale(
storageKey: string,
supportedLocales: readonly string[],
defaultLocale: string = 'en'
storageKey: string,
supportedLocales: readonly string[],
defaultLocale: string = 'en'
): string {
// Check localStorage first
const stored = getStoredLocale(storageKey, supportedLocales);
if (stored) {
return stored;
}
// Check localStorage first
const stored = getStoredLocale(storageKey, supportedLocales);
if (stored) {
return stored;
}
// Fall back to browser language
return detectBrowserLocale(supportedLocales, defaultLocale);
// Fall back to browser language
return detectBrowserLocale(supportedLocales, defaultLocale);
}
/**
@ -102,13 +102,13 @@ export function getInitialLocale(
* Examples: 'en-us' -> 'en-US', 'pt_BR' -> 'pt-BR'
*/
export function normalizeLocale(locale: string): string {
const parts = locale.replace('_', '-').split('-');
const parts = locale.replace('_', '-').split('-');
if (parts.length === 1) {
return parts[0].toLowerCase();
}
if (parts.length === 1) {
return parts[0].toLowerCase();
}
return `${parts[0].toLowerCase()}-${parts[1].toUpperCase()}`;
return `${parts[0].toLowerCase()}-${parts[1].toUpperCase()}`;
}
/**
@ -116,7 +116,7 @@ export function normalizeLocale(locale: string): string {
* Examples: 'pt-BR' -> 'pt', 'en-US' -> 'en'
*/
export function getBaseLanguage(locale: string): string {
return locale.split('-')[0].toLowerCase();
return locale.split('-')[0].toLowerCase();
}
/**
@ -124,126 +124,120 @@ export function getBaseLanguage(locale: string): string {
* Examples: matchesLanguage('pt-BR', 'pt') -> true
*/
export function matchesLanguage(locale: string, language: string): boolean {
const normalizedLocale = normalizeLocale(locale);
const normalizedLanguage = language.toLowerCase();
const normalizedLocale = normalizeLocale(locale);
const normalizedLanguage = language.toLowerCase();
return (
normalizedLocale === normalizedLanguage ||
getBaseLanguage(normalizedLocale) === normalizedLanguage
);
return (
normalizedLocale === normalizedLanguage ||
getBaseLanguage(normalizedLocale) === normalizedLanguage
);
}
/**
* Find best matching locale from supported list
*/
export function findBestMatch(
preferredLocale: string,
supportedLocales: readonly string[],
defaultLocale: string = 'en'
preferredLocale: string,
supportedLocales: readonly string[],
defaultLocale: string = 'en'
): string {
const normalized = normalizeLocale(preferredLocale);
const normalized = normalizeLocale(preferredLocale);
// Exact match
if (supportedLocales.includes(normalized)) {
return normalized;
}
// Exact match
if (supportedLocales.includes(normalized)) {
return normalized;
}
// Base language match
const base = getBaseLanguage(normalized);
if (supportedLocales.includes(base)) {
return base;
}
// Base language match
const base = getBaseLanguage(normalized);
if (supportedLocales.includes(base)) {
return base;
}
// Find any variant of the same language
const variant = supportedLocales.find(loc => getBaseLanguage(loc) === base);
if (variant) {
return variant;
}
// Find any variant of the same language
const variant = supportedLocales.find((loc) => getBaseLanguage(loc) === base);
if (variant) {
return variant;
}
return defaultLocale;
return defaultLocale;
}
/**
* Format number according to locale
*/
export function formatLocalizedNumber(
value: number,
locale: string = 'en',
options?: Intl.NumberFormatOptions
value: number,
locale: string = 'en',
options?: Intl.NumberFormatOptions
): string {
return new Intl.NumberFormat(locale, options).format(value);
return new Intl.NumberFormat(locale, options).format(value);
}
/**
* Format date according to locale
*/
export function formatLocalizedDate(
date: Date | string | number,
locale: string = 'en',
options?: Intl.DateTimeFormatOptions
date: Date | string | number,
locale: string = 'en',
options?: Intl.DateTimeFormatOptions
): string {
const dateObj = date instanceof Date ? date : new Date(date);
return new Intl.DateTimeFormat(locale, options).format(dateObj);
const dateObj = date instanceof Date ? date : new Date(date);
return new Intl.DateTimeFormat(locale, options).format(dateObj);
}
/**
* Format relative time according to locale
*/
export function formatRelativeTime(
date: Date | string | number,
locale: string = 'en',
style: 'long' | 'short' | 'narrow' = 'long'
date: Date | string | number,
locale: string = 'en',
style: 'long' | 'short' | 'narrow' = 'long'
): string {
const dateObj = date instanceof Date ? date : new Date(date);
const now = new Date();
const diffMs = dateObj.getTime() - now.getTime();
const diffSecs = Math.round(diffMs / 1000);
const diffMins = Math.round(diffSecs / 60);
const diffHours = Math.round(diffMins / 60);
const diffDays = Math.round(diffHours / 24);
const diffWeeks = Math.round(diffDays / 7);
const diffMonths = Math.round(diffDays / 30);
const diffYears = Math.round(diffDays / 365);
const dateObj = date instanceof Date ? date : new Date(date);
const now = new Date();
const diffMs = dateObj.getTime() - now.getTime();
const diffSecs = Math.round(diffMs / 1000);
const diffMins = Math.round(diffSecs / 60);
const diffHours = Math.round(diffMins / 60);
const diffDays = Math.round(diffHours / 24);
const diffWeeks = Math.round(diffDays / 7);
const diffMonths = Math.round(diffDays / 30);
const diffYears = Math.round(diffDays / 365);
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto', style });
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto', style });
if (Math.abs(diffSecs) < 60) {
return rtf.format(diffSecs, 'second');
} else if (Math.abs(diffMins) < 60) {
return rtf.format(diffMins, 'minute');
} else if (Math.abs(diffHours) < 24) {
return rtf.format(diffHours, 'hour');
} else if (Math.abs(diffDays) < 7) {
return rtf.format(diffDays, 'day');
} else if (Math.abs(diffWeeks) < 4) {
return rtf.format(diffWeeks, 'week');
} else if (Math.abs(diffMonths) < 12) {
return rtf.format(diffMonths, 'month');
} else {
return rtf.format(diffYears, 'year');
}
if (Math.abs(diffSecs) < 60) {
return rtf.format(diffSecs, 'second');
} else if (Math.abs(diffMins) < 60) {
return rtf.format(diffMins, 'minute');
} else if (Math.abs(diffHours) < 24) {
return rtf.format(diffHours, 'hour');
} else if (Math.abs(diffDays) < 7) {
return rtf.format(diffDays, 'day');
} else if (Math.abs(diffWeeks) < 4) {
return rtf.format(diffWeeks, 'week');
} else if (Math.abs(diffMonths) < 12) {
return rtf.format(diffMonths, 'month');
} else {
return rtf.format(diffYears, 'year');
}
}
/**
* Get plural form category
*/
export function getPluralCategory(
count: number,
locale: string = 'en'
): Intl.LDMLPluralRule {
const pr = new Intl.PluralRules(locale);
return pr.select(count);
export function getPluralCategory(count: number, locale: string = 'en'): Intl.LDMLPluralRule {
const pr = new Intl.PluralRules(locale);
return pr.select(count);
}
/**
* Interpolate values into a translation string
* Example: interpolate("Hello {name}!", { name: "World" }) -> "Hello World!"
*/
export function interpolate(
text: string,
values: Record<string, string | number>
): string {
return text.replace(/\{(\w+)\}/g, (match, key) => {
return key in values ? String(values[key]) : match;
});
export function interpolate(text: string, values: Record<string, string | number>): string {
return text.replace(/\{(\w+)\}/g, (match, key) => {
return key in values ? String(values[key]) : match;
});
}