init commit

This commit is contained in:
rxliuli
2025-11-04 05:03:50 +08:00
commit bce557cc2d
1396 changed files with 172991 additions and 0 deletions

142
src/utils/locale.ts Normal file
View File

@@ -0,0 +1,142 @@
import type { Opt } from '@jet/environment';
import { DEFAULT_STOREFRONT_CODE } from '~/constants/storefront';
import type {
NormalizedLocale,
NormalizedStorefront,
NormalizedLanguage,
} from '@jet-app/app-store/api/locale';
import type { Locale } from '@jet-app/app-store/foundation/dependencies/locale/locale';
import { TEXT_DIRECTION } from '@amp/web-app-components/src/constants';
import { getLocAttributes } from '@amp/web-apps-localization';
import { regions } from '~/utils/storefront-data';
import { getJet } from '~/jet/svelte';
export type NormalizedLocaleWithDefault = NormalizedLocale & {
isDefaultLanguage: boolean;
};
type LanguageDetails = {
languages: NormalizedLanguage[];
defaultLanguage: NormalizedLanguage;
};
export function normalizeStorefront(storefront: Opt<string>): {
storefront: NormalizedStorefront;
languages: NormalizedLanguage[];
defaultLanguage: NormalizedLanguage;
} {
const storefronts: Record<NormalizedStorefront, LanguageDetails> = {};
for (const { locales } of regions) {
for (const { id, language, isDefault } of locales) {
if (isDefault) {
storefronts[id as NormalizedStorefront] = {
languages: [],
defaultLanguage: language as NormalizedLanguage,
};
}
if (id in storefronts) {
storefronts[id as NormalizedStorefront].languages.push(
language as NormalizedLanguage,
);
}
}
}
const normalizedStorefront = (storefront || '').toLowerCase();
const chosenStorefront =
normalizedStorefront in storefronts
? (normalizedStorefront as NormalizedStorefront)
: DEFAULT_STOREFRONT_CODE;
return {
storefront: chosenStorefront,
...storefronts[chosenStorefront],
};
}
export function normalizeLanguage(
language: string,
languages: NormalizedLanguage[],
defaultLanguage: NormalizedLanguage,
): { language: NormalizedLanguage; isDefaultLanguage: boolean } {
function annotateReturn(language: NormalizedLanguage): {
language: NormalizedLanguage;
isDefaultLanguage: boolean;
} {
return {
language,
isDefaultLanguage: language === defaultLanguage,
};
}
// Prefer an exact match (ex. en-US matches en-US)
const exactMatch = findMatch(language, languages, (a, b) => a === b);
if (exactMatch) {
return annotateReturn(exactMatch);
}
// Try partial match (ex. fr-CA or fr matches fr-FR)
const partialMatch = findMatch(
language,
languages,
(a, b) => a.split('-')[0] === b.split('-')[0],
);
if (partialMatch) {
return annotateReturn(partialMatch);
}
// The only remaining choice is the storefront default
return annotateReturn(defaultLanguage);
}
function findMatch<T extends string>(
needle: string,
haystack: T[],
matches: (a: string, b: string) => boolean,
): Opt<T> {
return haystack.find((possibility) =>
matches(possibility.toLowerCase(), needle.toLowerCase()),
);
}
/**
* Gets the current Locale instance from the Svelte context.
*
* @return the active {@linkcode NormalizedLocale}
*/
export function getLocale(): NormalizedLocale {
let locale: Locale | undefined;
try {
const { objectGraph } = getJet();
locale = objectGraph.locale;
} catch {
throw new Error('`getLocale` called before `Jet.load`');
}
return {
storefront: locale.activeStorefront,
language: locale.activeLanguage,
};
}
/**
* Returns whether or not the document is in RTL mode, first based on the document's direction,
* with a fallback to the storefronts default writing direction.
*/
export function isRtl() {
const { storefront } = getLocale();
const { dir } = getLocAttributes(storefront);
return (
(typeof document !== 'undefined' &&
document.dir === TEXT_DIRECTION.RTL) ||
dir === TEXT_DIRECTION.RTL
);
}