@quilted/preact-localize 0.3.5 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/build/esm/hooks/formatting.mjs +4 -2
- package/build/esm/hooks/locale.mjs +4 -2
- package/build/esm/index.mjs +1 -4
- package/build/esm/routing/LocalizedLink.mjs +4 -4
- package/build/esm/routing/LocalizedNavigation.mjs +32 -41
- package/build/esm/routing/context.mjs +10 -4
- package/build/esnext/hooks/formatting.esnext +4 -2
- package/build/esnext/hooks/locale.esnext +4 -2
- package/build/esnext/index.esnext +1 -4
- package/build/esnext/routing/LocalizedLink.esnext +4 -4
- package/build/esnext/routing/LocalizedNavigation.esnext +27 -29
- package/build/esnext/routing/context.esnext +12 -4
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/typescript/context.d.ts +12 -3
- package/build/typescript/context.d.ts.map +1 -1
- package/build/typescript/hooks/formatting.d.ts +1 -1
- package/build/typescript/hooks/formatting.d.ts.map +1 -1
- package/build/typescript/hooks/locale.d.ts +1 -1
- package/build/typescript/hooks/locale.d.ts.map +1 -1
- package/build/typescript/index.d.ts +1 -3
- package/build/typescript/index.d.ts.map +1 -1
- package/build/typescript/routing/LocalizedLink.d.ts.map +1 -1
- package/build/typescript/routing/LocalizedNavigation.d.ts +8 -11
- package/build/typescript/routing/LocalizedNavigation.d.ts.map +1 -1
- package/build/typescript/routing/context.d.ts +1 -2
- package/build/typescript/routing/context.d.ts.map +1 -1
- package/build/typescript/routing.d.ts +0 -1
- package/build/typescript/routing.d.ts.map +1 -1
- package/package.json +7 -28
- package/source/context.ts +12 -6
- package/source/hooks/formatting.ts +4 -2
- package/source/hooks/locale.ts +4 -2
- package/source/index.ts +1 -6
- package/source/routing/LocalizedLink.tsx +4 -4
- package/source/routing/LocalizedNavigation.tsx +45 -59
- package/source/routing/context.ts +13 -4
- package/source/routing.ts +0 -1
- package/tsconfig.json +0 -1
- package/build/esm/Localization.mjs +0 -37
- package/build/esm/context.mjs +0 -6
- package/build/esm/request-router.mjs +0 -49
- package/build/esm/routing/LocalizedRouter.mjs +0 -34
- package/build/esnext/Localization.esnext +0 -44
- package/build/esnext/context.esnext +0 -6
- package/build/esnext/request-router.esnext +0 -48
- package/build/esnext/routing/LocalizedRouter.esnext +0 -32
- package/build/typescript/request-router.d.ts +0 -16
- package/build/typescript/request-router.d.ts.map +0 -1
- package/source/Localization.tsx +0 -61
- package/source/request-router.ts +0 -98
- package/source/routing/LocalizedRouter.ts +0 -46
package/source/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export {
|
|
2
2
|
createTranslate,
|
|
3
|
-
|
|
3
|
+
Localization,
|
|
4
4
|
parseAcceptLanguageHeader,
|
|
5
5
|
MissingTranslationError,
|
|
6
6
|
MissingTranslationPlaceholderError,
|
|
@@ -14,14 +14,9 @@ export type {
|
|
|
14
14
|
LocalizedDateTimeFormatOptions,
|
|
15
15
|
} from '@quilted/localize';
|
|
16
16
|
|
|
17
|
-
export {Localization} from './Localization.tsx';
|
|
18
17
|
export {useLocalizedFormatting} from './hooks/formatting.ts';
|
|
19
18
|
export {useLocale} from './hooks/locale.ts';
|
|
20
19
|
export {useAlternateURL} from './hooks/alternate-url.ts';
|
|
21
20
|
export {AlternateURL} from './components/AlternateURL.tsx';
|
|
22
|
-
export {LocalizedFormattingContext} from './context.ts';
|
|
23
21
|
|
|
24
22
|
export * from './routing.ts';
|
|
25
|
-
|
|
26
|
-
// export function useLocale(): string {}
|
|
27
|
-
// export function useTranslate(): Translate {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {ComponentProps} from 'preact';
|
|
2
2
|
import {useMemo} from 'preact/hooks';
|
|
3
|
-
import {useCurrentURL, Link,
|
|
3
|
+
import {useCurrentURL, Link, useNavigation} from '@quilted/preact-router';
|
|
4
4
|
|
|
5
5
|
import {useRouteLocalization} from './context.ts';
|
|
6
6
|
|
|
@@ -14,13 +14,13 @@ export function LocalizedLink({
|
|
|
14
14
|
locale: string;
|
|
15
15
|
to?: LinkProps['to'];
|
|
16
16
|
}) {
|
|
17
|
-
const
|
|
17
|
+
const navigation = useNavigation();
|
|
18
18
|
const url = useCurrentURL();
|
|
19
19
|
const {redirectURL} = useRouteLocalization();
|
|
20
20
|
|
|
21
21
|
const resolvedURL = useMemo(
|
|
22
|
-
() => redirectURL(to ?
|
|
23
|
-
[to, url, locale, redirectURL,
|
|
22
|
+
() => redirectURL(to ? navigation.resolve(to).url : url, {to: locale}),
|
|
23
|
+
[to, url, locale, redirectURL, navigation],
|
|
24
24
|
);
|
|
25
25
|
|
|
26
26
|
return <Link hrefLang={locale} to={resolvedURL} {...props} />;
|
|
@@ -1,63 +1,49 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {useMemo} from 'preact/hooks';
|
|
3
|
-
import {useBrowserDetails} from '@quilted/preact-browser';
|
|
4
|
-
import {Navigation, type RouteDefinition} from '@quilted/preact-router';
|
|
5
|
-
|
|
6
|
-
import {Localization} from '../Localization.tsx';
|
|
7
|
-
|
|
8
|
-
import {LocalizedRouter} from './LocalizedRouter.ts';
|
|
9
|
-
import {RouteLocalizationContext} from './context.ts';
|
|
10
|
-
import type {RouteLocalization} from './types.ts';
|
|
11
|
-
|
|
12
|
-
export interface LocalizedNavigationProps<Context = unknown> {
|
|
13
|
-
locale?: string;
|
|
14
|
-
router?: LocalizedRouter;
|
|
15
|
-
localization?: RouteLocalization;
|
|
16
|
-
routes?: readonly RouteDefinition<any, any, Context>[];
|
|
17
|
-
context?: Context;
|
|
18
|
-
}
|
|
1
|
+
import {Navigation, type NavigationOptions} from '@quilted/preact-router';
|
|
19
2
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
routes
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}: RenderableProps<LocalizedNavigationProps<Context>>) {
|
|
28
|
-
const browser = useBrowserDetails({optional: true});
|
|
29
|
-
const resolvedRouter = useMemo(
|
|
30
|
-
() =>
|
|
31
|
-
router ??
|
|
32
|
-
new LocalizedRouter(browser?.request.url, {localization: localization!}),
|
|
33
|
-
[router],
|
|
34
|
-
);
|
|
35
|
-
const resolvedLocalization = resolvedRouter.localization;
|
|
36
|
-
|
|
37
|
-
const localeFromEnvironment = browser?.locale.value;
|
|
38
|
-
|
|
39
|
-
let resolvedLocale: string;
|
|
40
|
-
|
|
41
|
-
if (explicitLocale) {
|
|
42
|
-
resolvedLocale = explicitLocale;
|
|
43
|
-
} else if (
|
|
44
|
-
localeFromEnvironment != null &&
|
|
45
|
-
localeFromEnvironment
|
|
46
|
-
.toLowerCase()
|
|
47
|
-
.startsWith(resolvedLocalization.locale.toLowerCase())
|
|
48
|
-
) {
|
|
49
|
-
resolvedLocale = localeFromEnvironment;
|
|
50
|
-
} else {
|
|
51
|
-
resolvedLocale = resolvedLocalization.locale;
|
|
3
|
+
import type {RouteLocalization, ResolvedRouteLocalization} from './types.ts';
|
|
4
|
+
|
|
5
|
+
export class LocalizedNavigation extends Navigation {
|
|
6
|
+
readonly routes: ResolvedRouteLocalization;
|
|
7
|
+
|
|
8
|
+
get locale() {
|
|
9
|
+
return this.routes.locale;
|
|
52
10
|
}
|
|
53
11
|
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
12
|
+
constructor(
|
|
13
|
+
initial: ConstructorParameters<typeof Navigation>[0],
|
|
14
|
+
{
|
|
15
|
+
routes,
|
|
16
|
+
isExternal: explicitIsExternal,
|
|
17
|
+
}: {routes: RouteLocalization} & Pick<NavigationOptions, 'isExternal'>,
|
|
18
|
+
) {
|
|
19
|
+
const {localeFromURL} = routes;
|
|
20
|
+
|
|
21
|
+
let matchedLocale: string | undefined;
|
|
22
|
+
|
|
23
|
+
super(initial, {
|
|
24
|
+
isExternal(url, currentURL) {
|
|
25
|
+
return (
|
|
26
|
+
matchedLocale !== localeFromURL(url) ||
|
|
27
|
+
(explicitIsExternal?.(url, currentURL) ?? false)
|
|
28
|
+
);
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const currentURL = this.currentRequest.url;
|
|
33
|
+
|
|
34
|
+
matchedLocale = localeFromURL(currentURL);
|
|
35
|
+
|
|
36
|
+
const resolvedLocalization: ResolvedRouteLocalization = {
|
|
37
|
+
locale: matchedLocale ?? routes.defaultLocale,
|
|
38
|
+
...routes,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
this.routes = resolvedLocalization;
|
|
42
|
+
|
|
43
|
+
const {pathname: rootPath} = routes.redirectURL(new URL('/', currentURL), {
|
|
44
|
+
to: resolvedLocalization.locale,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
if (rootPath.length > 1) Object.assign(this, {base: rootPath});
|
|
48
|
+
}
|
|
63
49
|
}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {useNavigation} from '@quilted/preact-router';
|
|
2
2
|
|
|
3
|
+
import {LocalizedNavigation} from './LocalizedNavigation.tsx';
|
|
3
4
|
import type {ResolvedRouteLocalization} from './types.ts';
|
|
4
5
|
|
|
5
|
-
export
|
|
6
|
-
|
|
6
|
+
export function useRouteLocalization(): ResolvedRouteLocalization {
|
|
7
|
+
const navigation = useNavigation();
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
if (!(navigation instanceof LocalizedNavigation)) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
'useRouteLocalization() requires a LocalizedNavigation instance to be provided in context. ' +
|
|
12
|
+
'Make sure you are passing a LocalizedNavigation to QuiltFrameworkContext.',
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return navigation.routes;
|
|
17
|
+
}
|
package/source/routing.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export {LocalizedLink} from './routing/LocalizedLink.tsx';
|
|
2
2
|
export {LocalizedNavigation} from './routing/LocalizedNavigation.tsx';
|
|
3
|
-
export {LocalizedRouter} from './routing/LocalizedRouter.ts';
|
|
4
3
|
export {useRouteLocalization} from './routing/context.ts';
|
|
5
4
|
export {createRouteLocalization} from './routing/localization/by-locale.ts';
|
|
6
5
|
export {createRoutePathLocalization} from './routing/localization/by-path.ts';
|
package/tsconfig.json
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'preact/hooks';
|
|
2
|
-
import { createLocalizedFormatting } from '@quilted/localize';
|
|
3
|
-
import { useBrowserDetails, HTMLAttributes } from '@quilted/preact-browser';
|
|
4
|
-
import { LocaleContext, LocalizedFormattingContext } from './context.mjs';
|
|
5
|
-
import { jsx, jsxs } from 'preact/jsx-runtime';
|
|
6
|
-
|
|
7
|
-
const RTL_LOCALES = new Set(['ar', 'arc', 'ckb', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ps', 'sd', 'ur', 'uz-AF', 'yi']);
|
|
8
|
-
function Localization({
|
|
9
|
-
locale: explicitLocale,
|
|
10
|
-
direction: explicitDirection,
|
|
11
|
-
children
|
|
12
|
-
}) {
|
|
13
|
-
const browserDetails = useBrowserDetails({
|
|
14
|
-
optional: true
|
|
15
|
-
});
|
|
16
|
-
const locale = explicitLocale ?? browserDetails?.locale.value ?? getLocaleFromEnvironment();
|
|
17
|
-
const formatting = useMemo(() => createLocalizedFormatting(locale), [locale]);
|
|
18
|
-
const direction = explicitDirection ?? (RTL_LOCALES.has(locale) ? 'rtl' : 'ltr');
|
|
19
|
-
return jsx(LocaleContext.Provider, {
|
|
20
|
-
value: locale,
|
|
21
|
-
children: jsxs(LocalizedFormattingContext.Provider, {
|
|
22
|
-
value: formatting,
|
|
23
|
-
children: [browserDetails && jsx(HTMLAttributes, {
|
|
24
|
-
lang: locale,
|
|
25
|
-
dir: direction
|
|
26
|
-
}), children]
|
|
27
|
-
})
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
function getLocaleFromEnvironment() {
|
|
31
|
-
if (typeof navigator === 'undefined') {
|
|
32
|
-
throw new Error(`Could not determine the locale automatically`);
|
|
33
|
-
}
|
|
34
|
-
return navigator.language;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export { Localization };
|
package/build/esm/context.mjs
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { RedirectResponse } from '@quilted/request-router';
|
|
2
|
-
import { parseAcceptLanguageHeader } from '@quilted/localize';
|
|
3
|
-
|
|
4
|
-
function createRequestRouterLocalization({
|
|
5
|
-
localization,
|
|
6
|
-
requestLocale: customRequestLocale
|
|
7
|
-
}) {
|
|
8
|
-
const {
|
|
9
|
-
matchLocale,
|
|
10
|
-
redirectURL,
|
|
11
|
-
defaultLocale,
|
|
12
|
-
localeFromURL
|
|
13
|
-
} = localization;
|
|
14
|
-
const getDefaultLocaleFromRequest = request => {
|
|
15
|
-
const acceptLanguage = request.headers.get('Accept-Language');
|
|
16
|
-
return acceptLanguage && parseAcceptLanguageHeader(acceptLanguage) || undefined;
|
|
17
|
-
};
|
|
18
|
-
const getLocaleForRequest = customRequestLocale ?? getDefaultLocaleFromRequest;
|
|
19
|
-
function localeRedirect(request, {
|
|
20
|
-
to,
|
|
21
|
-
...options
|
|
22
|
-
}) {
|
|
23
|
-
return new RedirectResponse(redirectURL(new URL(request.url), {
|
|
24
|
-
to
|
|
25
|
-
}), options);
|
|
26
|
-
}
|
|
27
|
-
return {
|
|
28
|
-
redirect: localeRedirect,
|
|
29
|
-
localizedRequestHandler(handler, {
|
|
30
|
-
include = () => true
|
|
31
|
-
} = {}) {
|
|
32
|
-
return async (request, ...args) => {
|
|
33
|
-
if (!include(request)) return handler(request, ...args);
|
|
34
|
-
const url = new URL(request.url);
|
|
35
|
-
const urlLocale = localeFromURL(url);
|
|
36
|
-
const requestLocale = getLocaleForRequest(request, () => getDefaultLocaleFromRequest(request));
|
|
37
|
-
const matchedLocale = (requestLocale == null ? undefined : matchLocale(requestLocale)) ?? defaultLocale;
|
|
38
|
-
if (urlLocale !== matchedLocale) {
|
|
39
|
-
return new RedirectResponse(redirectURL(url, {
|
|
40
|
-
to: matchedLocale
|
|
41
|
-
}));
|
|
42
|
-
}
|
|
43
|
-
return handler(request, ...args);
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export { createRequestRouterLocalization };
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Router } from '@quilted/preact-router';
|
|
2
|
-
|
|
3
|
-
class LocalizedRouter extends Router {
|
|
4
|
-
constructor(initial, {
|
|
5
|
-
localization,
|
|
6
|
-
isExternal: explicitIsExternal
|
|
7
|
-
}) {
|
|
8
|
-
const {
|
|
9
|
-
localeFromURL
|
|
10
|
-
} = localization;
|
|
11
|
-
super(initial, {
|
|
12
|
-
isExternal(url, currentURL) {
|
|
13
|
-
return matchedLocale !== localeFromURL(url) || (explicitIsExternal?.(url, currentURL) ?? false);
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
const currentURL = this.currentRequest.url;
|
|
17
|
-
const matchedLocale = localeFromURL(currentURL);
|
|
18
|
-
const resolvedLocalization = {
|
|
19
|
-
locale: matchedLocale ?? localization.defaultLocale,
|
|
20
|
-
...localization
|
|
21
|
-
};
|
|
22
|
-
this.localization = resolvedLocalization;
|
|
23
|
-
const {
|
|
24
|
-
pathname: rootPath
|
|
25
|
-
} = localization.redirectURL(new URL('/', currentURL), {
|
|
26
|
-
to: resolvedLocalization.locale
|
|
27
|
-
});
|
|
28
|
-
if (rootPath.length > 1) Object.assign(this, {
|
|
29
|
-
base: rootPath
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export { LocalizedRouter };
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs } from 'preact/jsx-runtime';
|
|
2
|
-
import { useMemo } from 'preact/hooks';
|
|
3
|
-
import { createLocalizedFormatting } from '@quilted/localize';
|
|
4
|
-
import { useBrowserDetails, HTMLAttributes } from '@quilted/preact-browser';
|
|
5
|
-
import { LocaleContext, LocalizedFormattingContext } from './context.esnext';
|
|
6
|
-
|
|
7
|
-
const RTL_LOCALES = /* @__PURE__ */ new Set([
|
|
8
|
-
"ar",
|
|
9
|
-
"arc",
|
|
10
|
-
"ckb",
|
|
11
|
-
"dv",
|
|
12
|
-
"fa",
|
|
13
|
-
"ha",
|
|
14
|
-
"he",
|
|
15
|
-
"khw",
|
|
16
|
-
"ks",
|
|
17
|
-
"ps",
|
|
18
|
-
"sd",
|
|
19
|
-
"ur",
|
|
20
|
-
"uz-AF",
|
|
21
|
-
"yi"
|
|
22
|
-
]);
|
|
23
|
-
function Localization({
|
|
24
|
-
locale: explicitLocale,
|
|
25
|
-
direction: explicitDirection,
|
|
26
|
-
children
|
|
27
|
-
}) {
|
|
28
|
-
const browserDetails = useBrowserDetails({ optional: true });
|
|
29
|
-
const locale = explicitLocale ?? browserDetails?.locale.value ?? getLocaleFromEnvironment();
|
|
30
|
-
const formatting = useMemo(() => createLocalizedFormatting(locale), [locale]);
|
|
31
|
-
const direction = explicitDirection ?? (RTL_LOCALES.has(locale) ? "rtl" : "ltr");
|
|
32
|
-
return /* @__PURE__ */ jsx(LocaleContext.Provider, { value: locale, children: /* @__PURE__ */ jsxs(LocalizedFormattingContext.Provider, { value: formatting, children: [
|
|
33
|
-
browserDetails && /* @__PURE__ */ jsx(HTMLAttributes, { lang: locale, dir: direction }),
|
|
34
|
-
children
|
|
35
|
-
] }) });
|
|
36
|
-
}
|
|
37
|
-
function getLocaleFromEnvironment() {
|
|
38
|
-
if (typeof navigator === "undefined") {
|
|
39
|
-
throw new Error(`Could not determine the locale automatically`);
|
|
40
|
-
}
|
|
41
|
-
return navigator.language;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export { Localization };
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { RedirectResponse } from '@quilted/request-router';
|
|
2
|
-
import { parseAcceptLanguageHeader } from '@quilted/localize';
|
|
3
|
-
|
|
4
|
-
function createRequestRouterLocalization({
|
|
5
|
-
localization,
|
|
6
|
-
requestLocale: customRequestLocale
|
|
7
|
-
}) {
|
|
8
|
-
const { matchLocale, redirectURL, defaultLocale, localeFromURL } = localization;
|
|
9
|
-
const getDefaultLocaleFromRequest = (request) => {
|
|
10
|
-
const acceptLanguage = request.headers.get("Accept-Language");
|
|
11
|
-
return acceptLanguage && parseAcceptLanguageHeader(acceptLanguage) || void 0;
|
|
12
|
-
};
|
|
13
|
-
const getLocaleForRequest = customRequestLocale ?? getDefaultLocaleFromRequest;
|
|
14
|
-
function localeRedirect(request, {
|
|
15
|
-
to,
|
|
16
|
-
...options
|
|
17
|
-
}) {
|
|
18
|
-
return new RedirectResponse(
|
|
19
|
-
redirectURL(new URL(request.url), { to }),
|
|
20
|
-
options
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
redirect: localeRedirect,
|
|
25
|
-
localizedRequestHandler(handler, { include = () => true } = {}) {
|
|
26
|
-
return async (request, ...args) => {
|
|
27
|
-
if (!include(request)) return handler(request, ...args);
|
|
28
|
-
const url = new URL(request.url);
|
|
29
|
-
const urlLocale = localeFromURL(url);
|
|
30
|
-
const requestLocale = getLocaleForRequest(
|
|
31
|
-
request,
|
|
32
|
-
() => getDefaultLocaleFromRequest(request)
|
|
33
|
-
);
|
|
34
|
-
const matchedLocale = (requestLocale == null ? void 0 : matchLocale(requestLocale)) ?? defaultLocale;
|
|
35
|
-
if (urlLocale !== matchedLocale) {
|
|
36
|
-
return new RedirectResponse(
|
|
37
|
-
redirectURL(url, {
|
|
38
|
-
to: matchedLocale
|
|
39
|
-
})
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
return handler(request, ...args);
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export { createRequestRouterLocalization };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { Router } from '@quilted/preact-router';
|
|
2
|
-
|
|
3
|
-
class LocalizedRouter extends Router {
|
|
4
|
-
localization;
|
|
5
|
-
constructor(initial, {
|
|
6
|
-
localization,
|
|
7
|
-
isExternal: explicitIsExternal
|
|
8
|
-
}) {
|
|
9
|
-
const { localeFromURL } = localization;
|
|
10
|
-
super(initial, {
|
|
11
|
-
isExternal(url, currentURL2) {
|
|
12
|
-
return matchedLocale !== localeFromURL(url) || (explicitIsExternal?.(url, currentURL2) ?? false);
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
const currentURL = this.currentRequest.url;
|
|
16
|
-
const matchedLocale = localeFromURL(currentURL);
|
|
17
|
-
const resolvedLocalization = {
|
|
18
|
-
locale: matchedLocale ?? localization.defaultLocale,
|
|
19
|
-
...localization
|
|
20
|
-
};
|
|
21
|
-
this.localization = resolvedLocalization;
|
|
22
|
-
const { pathname: rootPath } = localization.redirectURL(
|
|
23
|
-
new URL("/", currentURL),
|
|
24
|
-
{
|
|
25
|
-
to: resolvedLocalization.locale
|
|
26
|
-
}
|
|
27
|
-
);
|
|
28
|
-
if (rootPath.length > 1) Object.assign(this, { base: rootPath });
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export { LocalizedRouter };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { RedirectResponse, type RequestHandler } from '@quilted/request-router';
|
|
2
|
-
import type { RouteLocalization, ResolvedRouteLocalization, DefaultLocaleDefinition } from './routing.ts';
|
|
3
|
-
export type { RouteLocalization, ResolvedRouteLocalization, DefaultLocaleDefinition, };
|
|
4
|
-
export interface RequestRouterLocalization {
|
|
5
|
-
redirect(request: Request, options: {
|
|
6
|
-
to: string;
|
|
7
|
-
} & Pick<NonNullable<ConstructorParameters<typeof RedirectResponse>[1]>, 'status' | 'headers'>): Response;
|
|
8
|
-
localizedRequestHandler(handler: RequestHandler, options?: {
|
|
9
|
-
include?(request: Request): boolean;
|
|
10
|
-
}): RequestHandler;
|
|
11
|
-
}
|
|
12
|
-
export declare function createRequestRouterLocalization({ localization, requestLocale: customRequestLocale, }: {
|
|
13
|
-
localization: RouteLocalization;
|
|
14
|
-
requestLocale?(request: Request, getDefaultFromRequest: () => string | undefined): string | undefined;
|
|
15
|
-
}): RequestRouterLocalization;
|
|
16
|
-
//# sourceMappingURL=request-router.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request-router.d.ts","sourceRoot":"","sources":["../../source/request-router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAE,KAAK,cAAc,EAAC,MAAM,yBAAyB,CAAC;AAG9E,OAAO,KAAK,EACV,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,GACxB,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CACN,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE;QAAC,EAAE,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI,CAC1B,WAAW,CAAC,qBAAqB,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAC9D,QAAQ,GAAG,SAAS,CACrB,GACA,QAAQ,CAAC;IACZ,uBAAuB,CACrB,OAAO,EAAE,cAAc,EACvB,OAAO,CAAC,EAAE;QAAC,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAA;KAAC,GAC9C,cAAc,CAAC;CACnB;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,YAAY,EACZ,aAAa,EAAE,mBAAmB,GACnC,EAAE;IACD,YAAY,EAAE,iBAAiB,CAAC;IAChC,aAAa,CAAC,CACZ,OAAO,EAAE,OAAO,EAChB,qBAAqB,EAAE,MAAM,MAAM,GAAG,SAAS,GAC9C,MAAM,GAAG,SAAS,CAAC;CACvB,GAAG,yBAAyB,CA2D5B"}
|
package/source/Localization.tsx
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type {RenderableProps} from 'preact';
|
|
2
|
-
import {useMemo} from 'preact/hooks';
|
|
3
|
-
import {createLocalizedFormatting} from '@quilted/localize';
|
|
4
|
-
import {HTMLAttributes, useBrowserDetails} from '@quilted/preact-browser';
|
|
5
|
-
|
|
6
|
-
import {LocaleContext, LocalizedFormattingContext} from './context.ts';
|
|
7
|
-
|
|
8
|
-
export interface LocalizationProps {
|
|
9
|
-
locale?: string;
|
|
10
|
-
direction?: 'ltr' | 'rtl';
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const RTL_LOCALES = new Set([
|
|
14
|
-
'ar',
|
|
15
|
-
'arc',
|
|
16
|
-
'ckb',
|
|
17
|
-
'dv',
|
|
18
|
-
'fa',
|
|
19
|
-
'ha',
|
|
20
|
-
'he',
|
|
21
|
-
'khw',
|
|
22
|
-
'ks',
|
|
23
|
-
'ps',
|
|
24
|
-
'sd',
|
|
25
|
-
'ur',
|
|
26
|
-
'uz-AF',
|
|
27
|
-
'yi',
|
|
28
|
-
]);
|
|
29
|
-
|
|
30
|
-
export function Localization({
|
|
31
|
-
locale: explicitLocale,
|
|
32
|
-
direction: explicitDirection,
|
|
33
|
-
children,
|
|
34
|
-
}: RenderableProps<LocalizationProps>) {
|
|
35
|
-
const browserDetails = useBrowserDetails({optional: true});
|
|
36
|
-
const locale =
|
|
37
|
-
explicitLocale ??
|
|
38
|
-
browserDetails?.locale.value ??
|
|
39
|
-
getLocaleFromEnvironment();
|
|
40
|
-
|
|
41
|
-
const formatting = useMemo(() => createLocalizedFormatting(locale), [locale]);
|
|
42
|
-
const direction =
|
|
43
|
-
explicitDirection ?? (RTL_LOCALES.has(locale) ? 'rtl' : 'ltr');
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<LocaleContext.Provider value={locale}>
|
|
47
|
-
<LocalizedFormattingContext.Provider value={formatting}>
|
|
48
|
-
{browserDetails && <HTMLAttributes lang={locale} dir={direction} />}
|
|
49
|
-
{children}
|
|
50
|
-
</LocalizedFormattingContext.Provider>
|
|
51
|
-
</LocaleContext.Provider>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function getLocaleFromEnvironment() {
|
|
56
|
-
if (typeof navigator === 'undefined') {
|
|
57
|
-
throw new Error(`Could not determine the locale automatically`);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return navigator.language;
|
|
61
|
-
}
|
package/source/request-router.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import {RedirectResponse, type RequestHandler} from '@quilted/request-router';
|
|
2
|
-
import {parseAcceptLanguageHeader} from '@quilted/localize';
|
|
3
|
-
|
|
4
|
-
import type {
|
|
5
|
-
RouteLocalization,
|
|
6
|
-
ResolvedRouteLocalization,
|
|
7
|
-
DefaultLocaleDefinition,
|
|
8
|
-
} from './routing.ts';
|
|
9
|
-
|
|
10
|
-
export type {
|
|
11
|
-
RouteLocalization,
|
|
12
|
-
ResolvedRouteLocalization,
|
|
13
|
-
DefaultLocaleDefinition,
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export interface RequestRouterLocalization {
|
|
17
|
-
redirect(
|
|
18
|
-
request: Request,
|
|
19
|
-
options: {to: string} & Pick<
|
|
20
|
-
NonNullable<ConstructorParameters<typeof RedirectResponse>[1]>,
|
|
21
|
-
'status' | 'headers'
|
|
22
|
-
>,
|
|
23
|
-
): Response;
|
|
24
|
-
localizedRequestHandler(
|
|
25
|
-
handler: RequestHandler,
|
|
26
|
-
options?: {include?(request: Request): boolean},
|
|
27
|
-
): RequestHandler;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function createRequestRouterLocalization({
|
|
31
|
-
localization,
|
|
32
|
-
requestLocale: customRequestLocale,
|
|
33
|
-
}: {
|
|
34
|
-
localization: RouteLocalization;
|
|
35
|
-
requestLocale?(
|
|
36
|
-
request: Request,
|
|
37
|
-
getDefaultFromRequest: () => string | undefined,
|
|
38
|
-
): string | undefined;
|
|
39
|
-
}): RequestRouterLocalization {
|
|
40
|
-
const {matchLocale, redirectURL, defaultLocale, localeFromURL} = localization;
|
|
41
|
-
|
|
42
|
-
const getDefaultLocaleFromRequest = (request: Request) => {
|
|
43
|
-
const acceptLanguage = request.headers.get('Accept-Language');
|
|
44
|
-
return (
|
|
45
|
-
(acceptLanguage && parseAcceptLanguageHeader(acceptLanguage)) || undefined
|
|
46
|
-
);
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const getLocaleForRequest =
|
|
50
|
-
customRequestLocale ?? getDefaultLocaleFromRequest;
|
|
51
|
-
|
|
52
|
-
function localeRedirect(
|
|
53
|
-
request: Request,
|
|
54
|
-
{
|
|
55
|
-
to,
|
|
56
|
-
...options
|
|
57
|
-
}: {to: string} & Pick<
|
|
58
|
-
NonNullable<ConstructorParameters<typeof RedirectResponse>[1]>,
|
|
59
|
-
'status' | 'headers'
|
|
60
|
-
>,
|
|
61
|
-
): Response {
|
|
62
|
-
return new RedirectResponse(
|
|
63
|
-
redirectURL(new URL(request.url), {to}),
|
|
64
|
-
options,
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
redirect: localeRedirect,
|
|
70
|
-
localizedRequestHandler(
|
|
71
|
-
handler: RequestHandler,
|
|
72
|
-
{include = () => true}: {include?(request: Request): boolean} = {},
|
|
73
|
-
): RequestHandler {
|
|
74
|
-
return async (request, ...args) => {
|
|
75
|
-
if (!include(request)) return handler(request, ...args);
|
|
76
|
-
|
|
77
|
-
const url = new URL(request.url);
|
|
78
|
-
const urlLocale = localeFromURL(url);
|
|
79
|
-
const requestLocale = getLocaleForRequest(request, () =>
|
|
80
|
-
getDefaultLocaleFromRequest(request),
|
|
81
|
-
);
|
|
82
|
-
const matchedLocale =
|
|
83
|
-
(requestLocale == null ? undefined : matchLocale(requestLocale)) ??
|
|
84
|
-
defaultLocale;
|
|
85
|
-
|
|
86
|
-
if (urlLocale !== matchedLocale) {
|
|
87
|
-
return new RedirectResponse(
|
|
88
|
-
redirectURL(url, {
|
|
89
|
-
to: matchedLocale,
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return handler(request, ...args);
|
|
95
|
-
};
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
}
|