mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
chore(repo): prune dead code and duplicate abstractions (#3413)
This commit is contained in:
1 parent
c17091768c
commit
c9fdf8fead
2937 files changed
+42233
-176793
No files matched your search
@@ -0,0 +1,83 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {AllLocales, type LocaleCode, Locales} from '@fluxer/constants/src/Locales';
|
||||
|
||||
export const DEFAULT_LOCALE: LocaleCode = Locales.EN_US;
|
||||
const SUPPORTED_LOCALES: ReadonlyArray<LocaleCode> = AllLocales;
|
||||
const SUPPORTED_LOCALE_SET: ReadonlySet<LocaleCode> = new Set<LocaleCode>(SUPPORTED_LOCALES);
|
||||
const LANGUAGE_FALLBACK_BY_LANGUAGE_CODE: Record<string, LocaleCode> = {
|
||||
en: Locales.EN_US,
|
||||
es: Locales.ES_ES,
|
||||
nb: Locales.NO,
|
||||
nn: Locales.NO,
|
||||
no: Locales.NO,
|
||||
pt: Locales.PT_BR,
|
||||
zh: Locales.ZH_CN,
|
||||
sv: Locales.SV_SE,
|
||||
};
|
||||
const LOCALE_ALIASES: Partial<Record<LocaleCode, ReadonlyArray<string>>> = {
|
||||
[Locales.EN_US]: ['en'],
|
||||
[Locales.NO]: ['nb', 'nn'],
|
||||
[Locales.SV_SE]: ['sv'],
|
||||
};
|
||||
const NORMALIZED_LOCALE_TO_CODE = createNormalizedLocaleLookup();
|
||||
|
||||
export function normalizeLocaleCode(code: string): string {
|
||||
return code.trim().replace(/_/g, '-').toLowerCase();
|
||||
}
|
||||
|
||||
function isSupportedLocale(locale: LocaleCode): boolean {
|
||||
return SUPPORTED_LOCALE_SET.has(locale);
|
||||
}
|
||||
|
||||
export function getLocaleByCode(code: string): LocaleCode | null {
|
||||
const normalizedCode = normalizeLocaleCode(code);
|
||||
if (!normalizedCode) {
|
||||
return null;
|
||||
}
|
||||
const locale = NORMALIZED_LOCALE_TO_CODE.get(normalizedCode);
|
||||
return locale ?? null;
|
||||
}
|
||||
|
||||
export function getPreferredLocaleForLanguageCode(languageCode: string): LocaleCode | null {
|
||||
const normalizedLanguageCode = normalizeLocaleCode(languageCode);
|
||||
if (!normalizedLanguageCode) {
|
||||
return null;
|
||||
}
|
||||
const preferredLocale = LANGUAGE_FALLBACK_BY_LANGUAGE_CODE[normalizedLanguageCode];
|
||||
if (!preferredLocale) {
|
||||
return null;
|
||||
}
|
||||
if (!isSupportedLocale(preferredLocale)) {
|
||||
return null;
|
||||
}
|
||||
return preferredLocale;
|
||||
}
|
||||
|
||||
export function findLocaleByLanguagePrefix(languageCode: string): LocaleCode | null {
|
||||
const normalizedLanguageCode = normalizeLocaleCode(languageCode);
|
||||
if (!normalizedLanguageCode) {
|
||||
return null;
|
||||
}
|
||||
const languagePrefix = `${normalizedLanguageCode}-`;
|
||||
for (const locale of SUPPORTED_LOCALES) {
|
||||
if (locale.toLowerCase().startsWith(languagePrefix)) {
|
||||
return locale;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function createNormalizedLocaleLookup(): ReadonlyMap<string, LocaleCode> {
|
||||
const lookup = new Map<string, LocaleCode>();
|
||||
for (const locale of SUPPORTED_LOCALES) {
|
||||
lookup.set(normalizeLocaleCode(locale), locale);
|
||||
}
|
||||
for (const locale of SUPPORTED_LOCALES) {
|
||||
const aliases = LOCALE_ALIASES[locale] ?? [];
|
||||
for (const alias of aliases) {
|
||||
lookup.set(normalizeLocaleCode(alias), locale);
|
||||
}
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {type LocaleCode, Locales} from '@fluxer/constants/src/Locales';
|
||||
import {
|
||||
DEFAULT_LOCALE,
|
||||
findLocaleByLanguagePrefix,
|
||||
getLocaleByCode,
|
||||
getPreferredLocaleForLanguageCode,
|
||||
normalizeLocaleCode,
|
||||
} from '@fluxer/i18n/src/locale/catalog/LocaleCatalog';
|
||||
|
||||
interface AcceptLanguagePreference {
|
||||
locale: string;
|
||||
quality: number;
|
||||
}
|
||||
|
||||
const TRADITIONAL_CHINESE_SUBTAGS: ReadonlySet<string> = new Set(['hant', 'tw', 'hk', 'mo']);
|
||||
const SIMPLIFIED_CHINESE_SUBTAGS: ReadonlySet<string> = new Set(['hans', 'cn', 'sg']);
|
||||
|
||||
export function parseAcceptLanguage(acceptLanguageHeader: string | null | undefined): LocaleCode {
|
||||
if (!acceptLanguageHeader) {
|
||||
return DEFAULT_LOCALE;
|
||||
}
|
||||
try {
|
||||
const preferences = parseAcceptLanguagePreferences(acceptLanguageHeader);
|
||||
const exactLocaleMatch = findExactLocaleMatch(preferences);
|
||||
if (exactLocaleMatch) {
|
||||
return exactLocaleMatch;
|
||||
}
|
||||
const languageFallbackMatch = findLanguageFallbackMatch(preferences);
|
||||
if (languageFallbackMatch) {
|
||||
return languageFallbackMatch;
|
||||
}
|
||||
return DEFAULT_LOCALE;
|
||||
} catch {
|
||||
return DEFAULT_LOCALE;
|
||||
}
|
||||
}
|
||||
|
||||
function parseAcceptLanguagePreferences(acceptLanguageHeader: string): Array<AcceptLanguagePreference> {
|
||||
return acceptLanguageHeader
|
||||
.split(',')
|
||||
.map((languageToken) => parseLanguagePreference(languageToken))
|
||||
.sort((a, b) => b.quality - a.quality);
|
||||
}
|
||||
|
||||
function parseLanguagePreference(languageToken: string): AcceptLanguagePreference {
|
||||
const parts = languageToken.trim().split(';');
|
||||
const locale = parts[0].trim();
|
||||
const quality = parseQualityValue(parts[1]);
|
||||
return {
|
||||
locale,
|
||||
quality,
|
||||
};
|
||||
}
|
||||
|
||||
function parseQualityValue(rawQuality: string | undefined): number {
|
||||
const qualityMatch = rawQuality?.match(/q=([\d.]+)/);
|
||||
if (!qualityMatch) {
|
||||
return 1.0;
|
||||
}
|
||||
const parsedQuality = Number.parseFloat(qualityMatch[1]);
|
||||
if (!Number.isFinite(parsedQuality)) {
|
||||
return 1.0;
|
||||
}
|
||||
return parsedQuality;
|
||||
}
|
||||
|
||||
function findExactLocaleMatch(preferences: ReadonlyArray<AcceptLanguagePreference>): LocaleCode | null {
|
||||
for (const {locale} of preferences) {
|
||||
const exactMatch = getLocaleByCode(locale);
|
||||
if (exactMatch) {
|
||||
return exactMatch;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findLanguageFallbackMatch(preferences: ReadonlyArray<AcceptLanguagePreference>): LocaleCode | null {
|
||||
for (const {locale} of preferences) {
|
||||
const [languageCode = '', ...subtags] = normalizeLocaleCode(locale).split('-');
|
||||
const chineseVariantLocale = findChineseVariantLocale(languageCode, subtags);
|
||||
if (chineseVariantLocale) {
|
||||
return chineseVariantLocale;
|
||||
}
|
||||
const languageLocale = getLocaleByCode(languageCode);
|
||||
if (languageLocale) {
|
||||
return languageLocale;
|
||||
}
|
||||
const preferredFallbackLocale = getPreferredLocaleForLanguageCode(languageCode);
|
||||
if (preferredFallbackLocale) {
|
||||
return preferredFallbackLocale;
|
||||
}
|
||||
const prefixMatchLocale = findLocaleByLanguagePrefix(languageCode);
|
||||
if (prefixMatchLocale) {
|
||||
return prefixMatchLocale;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findChineseVariantLocale(languageCode: string, subtags: ReadonlyArray<string>): LocaleCode | null {
|
||||
if (languageCode !== 'zh') {
|
||||
return null;
|
||||
}
|
||||
for (const subtag of subtags) {
|
||||
if (TRADITIONAL_CHINESE_SUBTAGS.has(subtag)) {
|
||||
return Locales.ZH_TW;
|
||||
}
|
||||
if (SIMPLIFIED_CHINESE_SUBTAGS.has(subtag)) {
|
||||
return Locales.ZH_CN;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
export function identityLocale(locale: string): string {
|
||||
return locale;
|
||||
}
|
||||
@@ -11,7 +11,6 @@ export interface StaticI18nConfig<TKey extends string, TValue, TVariables> {
|
||||
defaultLocale: string;
|
||||
defaultMessages: Record<TKey, TValue>;
|
||||
localeMessages: Record<string, StaticLocaleMessages<TKey, TValue>>;
|
||||
normalizeLocale?: (locale: string) => string;
|
||||
onWarning?: (message: string) => void;
|
||||
validateVariables?: (key: TKey, template: TValue, variables: TVariables) => string | null;
|
||||
messageFormatOptions?: MessageFormatOptions<'string'>;
|
||||
|
||||
@@ -19,7 +19,7 @@ export function getEffectiveStaticLocale<TKey extends string, TValue, TVariables
|
||||
if (!locale) {
|
||||
return config.defaultLocale;
|
||||
}
|
||||
const normalizedLocale = config.normalizeLocale?.(locale) ?? locale;
|
||||
const normalizedLocale = locale;
|
||||
if (!hasStaticLocale(config, normalizedLocale)) {
|
||||
config.onWarning?.(`Unsupported locale, falling back to ${config.defaultLocale}: ${locale}`);
|
||||
return config.defaultLocale;
|
||||
|
||||
Reference in new issue
Block a user