@quilted/preact-localize 0.1.0 → 0.3.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/build/esm/Localization.mjs +11 -3
  3. package/build/esm/index.mjs +2 -2
  4. package/build/esm/request-router.mjs +5 -5
  5. package/build/esm/routing/LocalizedLink.mjs +6 -6
  6. package/build/esm/routing/LocalizedNavigation.mjs +47 -0
  7. package/build/esm/routing/LocalizedRouter.mjs +34 -0
  8. package/build/esm/routing/localization/by-locale.mjs +5 -5
  9. package/build/esnext/Localization.esnext +9 -3
  10. package/build/esnext/index.esnext +2 -2
  11. package/build/esnext/request-router.esnext +5 -6
  12. package/build/esnext/routing/LocalizedLink.esnext +7 -7
  13. package/build/esnext/routing/LocalizedNavigation.esnext +35 -0
  14. package/build/esnext/routing/LocalizedRouter.esnext +32 -0
  15. package/build/esnext/routing/localization/by-locale.esnext +9 -13
  16. package/build/tsconfig.tsbuildinfo +1 -1
  17. package/build/typescript/Localization.d.ts +2 -2
  18. package/build/typescript/Localization.d.ts.map +1 -1
  19. package/build/typescript/index.d.ts +0 -1
  20. package/build/typescript/index.d.ts.map +1 -1
  21. package/build/typescript/routing/LocalizedNavigation.d.ts +13 -0
  22. package/build/typescript/routing/LocalizedNavigation.d.ts.map +1 -0
  23. package/build/typescript/routing/LocalizedRouter.d.ts +9 -0
  24. package/build/typescript/routing/LocalizedRouter.d.ts.map +1 -0
  25. package/build/typescript/routing/types.d.ts +2 -2
  26. package/build/typescript/routing.d.ts +2 -1
  27. package/build/typescript/routing.d.ts.map +1 -1
  28. package/package.json +5 -5
  29. package/source/Localization.tsx +13 -4
  30. package/source/index.ts +0 -1
  31. package/source/request-router.ts +4 -4
  32. package/source/routing/LocalizedLink.tsx +7 -7
  33. package/source/routing/LocalizedNavigation.tsx +63 -0
  34. package/source/routing/LocalizedRouter.ts +46 -0
  35. package/source/routing/localization/by-locale.ts +5 -5
  36. package/source/routing/types.ts +2 -2
  37. package/source/routing.ts +2 -1
  38. package/tsconfig.json +1 -5
  39. package/build/esm/hooks/locale-from-environment.mjs +0 -15
  40. package/build/esm/routing/LocalizedRouting.mjs +0 -65
  41. package/build/esnext/hooks/locale-from-environment.esnext +0 -13
  42. package/build/esnext/routing/LocalizedRouting.esnext +0 -64
  43. package/build/typescript/routing/LocalizedRouting.d.ts +0 -9
  44. package/build/typescript/routing/LocalizedRouting.d.ts.map +0 -1
  45. package/source/hooks/locale-from-environment.ts +0 -15
  46. package/source/routing/LocalizedRouting.tsx +0 -94
@@ -0,0 +1,46 @@
1
+ import {Router, type RouterOptions} from '@quilted/preact-router';
2
+
3
+ import type {RouteLocalization, ResolvedRouteLocalization} from './types.ts';
4
+
5
+ export class LocalizedRouter extends Router {
6
+ readonly localization: ResolvedRouteLocalization;
7
+
8
+ constructor(
9
+ initial: ConstructorParameters<typeof Router>[0],
10
+ {
11
+ localization,
12
+ isExternal: explicitIsExternal,
13
+ }: {localization: RouteLocalization} & Pick<RouterOptions, 'isExternal'>,
14
+ ) {
15
+ const {localeFromURL} = localization;
16
+
17
+ super(initial, {
18
+ isExternal(url, currentURL) {
19
+ return (
20
+ matchedLocale !== localeFromURL(url) ||
21
+ (explicitIsExternal?.(url, currentURL) ?? false)
22
+ );
23
+ },
24
+ });
25
+
26
+ const currentURL = this.currentRequest.url;
27
+
28
+ const matchedLocale = localeFromURL(currentURL);
29
+
30
+ const resolvedLocalization: ResolvedRouteLocalization = {
31
+ locale: matchedLocale ?? localization.defaultLocale,
32
+ ...localization,
33
+ };
34
+
35
+ this.localization = resolvedLocalization;
36
+
37
+ const {pathname: rootPath} = localization.redirectURL(
38
+ new URL('/', currentURL),
39
+ {
40
+ to: resolvedLocalization.locale,
41
+ },
42
+ );
43
+
44
+ if (rootPath.length > 1) Object.assign(this, {base: rootPath});
45
+ }
46
+ }
@@ -15,9 +15,9 @@ export function createRouteLocalization({
15
15
 
16
16
  return {
17
17
  locales,
18
- redirectUrl,
18
+ redirectURL,
19
19
  matchLocale,
20
- localeFromUrl,
20
+ localeFromURL,
21
21
  defaultLocale,
22
22
  };
23
23
 
@@ -29,7 +29,7 @@ export function createRouteLocalization({
29
29
  );
30
30
  }
31
31
 
32
- function localeFromUrl(url: URL) {
32
+ function localeFromURL(url: URL) {
33
33
  const hostname = url.hostname.toLowerCase();
34
34
  const pathname = normalizePath(url.pathname.toLowerCase());
35
35
 
@@ -42,8 +42,8 @@ export function createRouteLocalization({
42
42
  }
43
43
  }
44
44
 
45
- function redirectUrl(from: URL, {to: toLocale}: {to: string}) {
46
- const fromLocale = localeFromUrl(from);
45
+ function redirectURL(from: URL, {to: toLocale}: {to: string}) {
46
+ const fromLocale = localeFromURL(from);
47
47
  const toUrl = new URL(from);
48
48
 
49
49
  if (fromLocale === toLocale) return toUrl;
@@ -2,8 +2,8 @@ export interface RouteLocalization {
2
2
  readonly locales: string[];
3
3
  readonly defaultLocale: string;
4
4
  matchLocale(locale: string): string | undefined;
5
- redirectUrl(from: URL, options: {to: string}): URL;
6
- localeFromUrl(url: URL): string | undefined;
5
+ redirectURL(from: URL, options: {to: string}): URL;
6
+ localeFromURL(url: URL): string | undefined;
7
7
  }
8
8
 
9
9
  export interface ResolvedRouteLocalization extends RouteLocalization {
package/source/routing.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export {LocalizedLink} from './routing/LocalizedLink.tsx';
2
- export {LocalizedRouting} from './routing/LocalizedRouting.tsx';
2
+ export {LocalizedNavigation} from './routing/LocalizedNavigation.tsx';
3
+ export {LocalizedRouter} from './routing/LocalizedRouter.ts';
3
4
  export {useRouteLocalization} from './routing/context.ts';
4
5
  export {createRouteLocalization} from './routing/localization/by-locale.ts';
5
6
  export {createRoutePathLocalization} from './routing/localization/by-path.ts';
package/tsconfig.json CHANGED
@@ -1,12 +1,8 @@
1
1
  {
2
- "extends": "@quilted/typescript/tsconfig.project.json",
2
+ "extends": "@quilted/typescript/tsconfig.package.json",
3
3
  "compilerOptions": {
4
- "rootDir": "source",
5
- "outDir": "build/typescript",
6
4
  "jsxImportSource": "preact"
7
5
  },
8
- "include": ["source"],
9
- "exclude": ["*.test.ts", "*.test.tsx"],
10
6
  "references": [
11
7
  {"path": "../localize"},
12
8
  {"path": "../preact-browser"},
@@ -1,15 +0,0 @@
1
- import { parseAcceptLanguageHeader } from '@quilted/localize';
2
- import { useBrowserDetails } from '@quilted/preact-browser';
3
-
4
- function useLocaleFromEnvironment() {
5
- if (typeof navigator === 'object' && navigator.language) {
6
- return navigator.language;
7
- }
8
- const browserDetails = useBrowserDetails({
9
- optional: true
10
- });
11
- const acceptLanguage = browserDetails?.request.headers?.get('Accept-Language');
12
- return acceptLanguage && parseAcceptLanguageHeader(acceptLanguage);
13
- }
14
-
15
- export { useLocaleFromEnvironment };
@@ -1,65 +0,0 @@
1
- import { useMemo, useCallback } from 'preact/hooks';
2
- import { useInitialURL, Routing } from '@quilted/preact-router';
3
- import { Localization } from '../Localization.mjs';
4
- import { useLocaleFromEnvironment } from '../hooks/locale-from-environment.mjs';
5
- import { RouteLocalizationContext } from './context.mjs';
6
- import { jsx } from 'preact/jsx-runtime';
7
-
8
- function LocalizedRouting({
9
- locale: explicitLocale,
10
- localization,
11
- children,
12
- isExternal: isExplicitlyExternal,
13
- ...props
14
- }) {
15
- const initialUrl = useInitialURL();
16
- const localeFromEnvironment = useLocaleFromEnvironment();
17
- const {
18
- prefix,
19
- isExternal: isExternalByRouteLocale,
20
- resolvedLocalization
21
- } = useMemo(() => {
22
- const {
23
- localeFromUrl
24
- } = localization;
25
- const matchedLocale = initialUrl && localeFromUrl(initialUrl);
26
- const resolvedLocalization = {
27
- locale: matchedLocale ?? localization.defaultLocale,
28
- ...localization
29
- };
30
- const rootUrl = localization.redirectUrl(new URL('/', initialUrl ?? 'https://example.com'), {
31
- to: resolvedLocalization.locale
32
- });
33
- return {
34
- prefix: rootUrl.pathname.length > 1 ? rootUrl.pathname : undefined,
35
- isExternal: url => matchedLocale !== localeFromUrl(url),
36
- resolvedLocalization
37
- };
38
- }, [initialUrl, localization]);
39
- const isExternal = useCallback((url, currentUrl) => {
40
- return isExternalByRouteLocale(url) || (isExplicitlyExternal?.(url, currentUrl) ?? false);
41
- }, [isExplicitlyExternal, isExternalByRouteLocale]);
42
- let resolvedLocale;
43
- if (explicitLocale) {
44
- resolvedLocale = explicitLocale;
45
- } else if (localeFromEnvironment != null && localeFromEnvironment.toLowerCase().startsWith(resolvedLocalization.locale.toLowerCase())) {
46
- resolvedLocale = localeFromEnvironment;
47
- } else {
48
- resolvedLocale = resolvedLocalization.locale;
49
- }
50
- return jsx(Routing, {
51
- ...props,
52
- prefix: prefix,
53
- url: initialUrl,
54
- isExternal: isExternal,
55
- children: jsx(Localization, {
56
- locale: resolvedLocale,
57
- children: jsx(RouteLocalizationContext.Provider, {
58
- value: resolvedLocalization,
59
- children: children
60
- })
61
- })
62
- });
63
- }
64
-
65
- export { LocalizedRouting };
@@ -1,13 +0,0 @@
1
- import { parseAcceptLanguageHeader } from '@quilted/localize';
2
- import { useBrowserDetails } from '@quilted/preact-browser';
3
-
4
- function useLocaleFromEnvironment() {
5
- if (typeof navigator === "object" && navigator.language) {
6
- return navigator.language;
7
- }
8
- const browserDetails = useBrowserDetails({ optional: true });
9
- const acceptLanguage = browserDetails?.request.headers?.get("Accept-Language");
10
- return acceptLanguage && parseAcceptLanguageHeader(acceptLanguage);
11
- }
12
-
13
- export { useLocaleFromEnvironment };
@@ -1,64 +0,0 @@
1
- import { jsx } from 'preact/jsx-runtime';
2
- import { useMemo, useCallback } from 'preact/hooks';
3
- import { useInitialURL, Routing } from '@quilted/preact-router';
4
- import { Localization } from '../Localization.esnext';
5
- import { useLocaleFromEnvironment } from '../hooks/locale-from-environment.esnext';
6
- import { RouteLocalizationContext } from './context.esnext';
7
-
8
- function LocalizedRouting({
9
- locale: explicitLocale,
10
- localization,
11
- children,
12
- isExternal: isExplicitlyExternal,
13
- ...props
14
- }) {
15
- const initialUrl = useInitialURL();
16
- const localeFromEnvironment = useLocaleFromEnvironment();
17
- const {
18
- prefix,
19
- isExternal: isExternalByRouteLocale,
20
- resolvedLocalization
21
- } = useMemo(() => {
22
- const { localeFromUrl } = localization;
23
- const matchedLocale = initialUrl && localeFromUrl(initialUrl);
24
- const resolvedLocalization2 = {
25
- locale: matchedLocale ?? localization.defaultLocale,
26
- ...localization
27
- };
28
- const rootUrl = localization.redirectUrl(
29
- new URL("/", initialUrl ?? "https://example.com"),
30
- { to: resolvedLocalization2.locale }
31
- );
32
- return {
33
- prefix: rootUrl.pathname.length > 1 ? rootUrl.pathname : void 0,
34
- isExternal: (url) => matchedLocale !== localeFromUrl(url),
35
- resolvedLocalization: resolvedLocalization2
36
- };
37
- }, [initialUrl, localization]);
38
- const isExternal = useCallback(
39
- (url, currentUrl) => {
40
- return isExternalByRouteLocale(url) || (isExplicitlyExternal?.(url, currentUrl) ?? false);
41
- },
42
- [isExplicitlyExternal, isExternalByRouteLocale]
43
- );
44
- let resolvedLocale;
45
- if (explicitLocale) {
46
- resolvedLocale = explicitLocale;
47
- } else if (localeFromEnvironment != null && localeFromEnvironment.toLowerCase().startsWith(resolvedLocalization.locale.toLowerCase())) {
48
- resolvedLocale = localeFromEnvironment;
49
- } else {
50
- resolvedLocale = resolvedLocalization.locale;
51
- }
52
- return /* @__PURE__ */ jsx(
53
- Routing,
54
- {
55
- ...props,
56
- prefix,
57
- url: initialUrl,
58
- isExternal,
59
- children: /* @__PURE__ */ jsx(Localization, { locale: resolvedLocale, children: /* @__PURE__ */ jsx(RouteLocalizationContext.Provider, { value: resolvedLocalization, children }) })
60
- }
61
- );
62
- }
63
-
64
- export { LocalizedRouting };
@@ -1,9 +0,0 @@
1
- import type { ComponentProps } from 'preact';
2
- import { Routing } from '@quilted/preact-router';
3
- import type { RouteLocalization } from './types.ts';
4
- export type LocalizedRoutingProps = Omit<ComponentProps<typeof Routing>, 'prefix' | 'initialUrl'> & {
5
- locale?: string;
6
- localization: RouteLocalization;
7
- };
8
- export declare function LocalizedRouting({ locale: explicitLocale, localization, children, isExternal: isExplicitlyExternal, ...props }: LocalizedRoutingProps): import("preact").JSX.Element;
9
- //# sourceMappingURL=LocalizedRouting.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LocalizedRouting.d.ts","sourceRoot":"","sources":["../../../source/routing/LocalizedRouting.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,QAAQ,CAAC;AAE3C,OAAO,EAAC,OAAO,EAAgB,MAAM,wBAAwB,CAAC;AAK9D,OAAO,KAAK,EAAC,iBAAiB,EAA4B,MAAM,YAAY,CAAC;AAG7E,MAAM,MAAM,qBAAqB,GAAG,IAAI,CACtC,cAAc,CAAC,OAAO,OAAO,CAAC,EAC9B,QAAQ,GAAG,YAAY,CACxB,GAAG;IACF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,iBAAiB,CAAC;CACjC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EAAE,cAAc,EACtB,YAAY,EACZ,QAAQ,EACR,UAAU,EAAE,oBAAoB,EAChC,GAAG,KAAK,EACT,EAAE,qBAAqB,gCAqEvB"}
@@ -1,15 +0,0 @@
1
- import {parseAcceptLanguageHeader} from '@quilted/localize';
2
- import {useBrowserDetails} from '@quilted/preact-browser';
3
-
4
- export function useLocaleFromEnvironment() {
5
- if (typeof navigator === 'object' && navigator.language) {
6
- return navigator.language;
7
- }
8
-
9
- const browserDetails = useBrowserDetails({optional: true});
10
-
11
- const acceptLanguage =
12
- browserDetails?.request.headers?.get('Accept-Language');
13
-
14
- return acceptLanguage && parseAcceptLanguageHeader(acceptLanguage);
15
- }
@@ -1,94 +0,0 @@
1
- import type {ComponentProps} from 'preact';
2
- import {useCallback, useMemo} from 'preact/hooks';
3
- import {Routing, useInitialURL} from '@quilted/preact-router';
4
-
5
- import {Localization} from '../Localization.tsx';
6
- import {useLocaleFromEnvironment} from '../hooks/locale-from-environment.ts';
7
-
8
- import type {RouteLocalization, ResolvedRouteLocalization} from './types.ts';
9
- import {RouteLocalizationContext} from './context.ts';
10
-
11
- export type LocalizedRoutingProps = Omit<
12
- ComponentProps<typeof Routing>,
13
- 'prefix' | 'initialUrl'
14
- > & {
15
- locale?: string;
16
- localization: RouteLocalization;
17
- };
18
-
19
- export function LocalizedRouting({
20
- locale: explicitLocale,
21
- localization,
22
- children,
23
- isExternal: isExplicitlyExternal,
24
- ...props
25
- }: LocalizedRoutingProps) {
26
- const initialUrl = useInitialURL();
27
- const localeFromEnvironment = useLocaleFromEnvironment();
28
-
29
- const {
30
- prefix,
31
- isExternal: isExternalByRouteLocale,
32
- resolvedLocalization,
33
- } = useMemo(() => {
34
- const {localeFromUrl} = localization;
35
-
36
- const matchedLocale = initialUrl && localeFromUrl(initialUrl);
37
-
38
- const resolvedLocalization: ResolvedRouteLocalization = {
39
- locale: matchedLocale ?? localization.defaultLocale,
40
- ...localization,
41
- };
42
-
43
- const rootUrl = localization.redirectUrl(
44
- new URL('/', initialUrl ?? 'https://example.com'),
45
- {to: resolvedLocalization.locale},
46
- );
47
-
48
- return {
49
- prefix: rootUrl.pathname.length > 1 ? rootUrl.pathname : undefined,
50
- isExternal: (url: URL) => matchedLocale !== localeFromUrl(url),
51
- resolvedLocalization,
52
- };
53
- }, [initialUrl, localization]);
54
-
55
- const isExternal = useCallback(
56
- (url: URL, currentUrl: URL) => {
57
- return (
58
- isExternalByRouteLocale(url) ||
59
- (isExplicitlyExternal?.(url, currentUrl) ?? false)
60
- );
61
- },
62
- [isExplicitlyExternal, isExternalByRouteLocale],
63
- );
64
-
65
- let resolvedLocale: string;
66
-
67
- if (explicitLocale) {
68
- resolvedLocale = explicitLocale;
69
- } else if (
70
- localeFromEnvironment != null &&
71
- localeFromEnvironment
72
- .toLowerCase()
73
- .startsWith(resolvedLocalization.locale.toLowerCase())
74
- ) {
75
- resolvedLocale = localeFromEnvironment;
76
- } else {
77
- resolvedLocale = resolvedLocalization.locale;
78
- }
79
-
80
- return (
81
- <Routing
82
- {...props}
83
- prefix={prefix}
84
- url={initialUrl}
85
- isExternal={isExternal}
86
- >
87
- <Localization locale={resolvedLocale}>
88
- <RouteLocalizationContext.Provider value={resolvedLocalization}>
89
- {children}
90
- </RouteLocalizationContext.Provider>
91
- </Localization>
92
- </Routing>
93
- );
94
- }