@lovalingo/lovalingo 0.5.29 → 0.6.0
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/README.md +34 -0
- package/dist/chunk-2FZR2AKF.mjs +88 -0
- package/dist/chunk-7D5LBV45.mjs +46 -0
- package/dist/chunk-CJOSN7RA.mjs +90 -0
- package/dist/chunk-VAHA2TOX.mjs +3440 -0
- package/dist/chunk-ZMRCSUM7.mjs +26 -0
- package/dist/chunk-ZVYKEEUF.mjs +220 -0
- package/dist/core.d.mts +131 -0
- package/dist/core.d.ts +131 -0
- package/dist/core.js +3561 -0
- package/dist/core.mjs +19 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -25
- package/dist/index.js +3885 -28
- package/dist/index.mjs +33 -0
- package/dist/react-router.d.mts +101 -0
- package/dist/react-router.d.ts +101 -0
- package/dist/react-router.js +353 -0
- package/dist/react-router.mjs +14 -0
- package/dist/tanstack-router.d.mts +22 -0
- package/dist/tanstack-router.d.ts +22 -0
- package/dist/tanstack-router.js +162 -0
- package/dist/tanstack-router.mjs +8 -0
- package/package.json +34 -3
- package/dist/__tests__/languageFlags.test.d.ts +0 -1
- package/dist/__tests__/languageFlags.test.js +0 -42
- package/dist/__tests__/mergeEntitlements.test.d.ts +0 -1
- package/dist/__tests__/mergeEntitlements.test.js +0 -27
- package/dist/components/AixsterProvider.d.ts +0 -1
- package/dist/components/AixsterProvider.js +0 -1
- package/dist/components/LangLink.d.ts +0 -20
- package/dist/components/LangLink.js +0 -38
- package/dist/components/LangRouter.d.ts +0 -37
- package/dist/components/LangRouter.js +0 -191
- package/dist/components/LanguageSwitcher.d.ts +0 -17
- package/dist/components/LanguageSwitcher.js +0 -257
- package/dist/components/LovalingoProvider.d.ts +0 -10
- package/dist/components/LovalingoProvider.js +0 -413
- package/dist/components/NavigationOverlay.d.ts +0 -6
- package/dist/components/NavigationOverlay.js +0 -22
- package/dist/components/provider/__tests__/seoUtils.test.d.ts +0 -1
- package/dist/components/provider/__tests__/seoUtils.test.js +0 -13
- package/dist/components/provider/editModeUtils.d.ts +0 -6
- package/dist/components/provider/editModeUtils.js +0 -59
- package/dist/components/provider/localeUtils.d.ts +0 -8
- package/dist/components/provider/localeUtils.js +0 -46
- package/dist/components/provider/providerConstants.d.ts +0 -12
- package/dist/components/provider/providerConstants.js +0 -11
- package/dist/components/provider/seoUtils.d.ts +0 -8
- package/dist/components/provider/seoUtils.js +0 -118
- package/dist/components/provider/useEditModeOverlay.d.ts +0 -7
- package/dist/components/provider/useEditModeOverlay.js +0 -134
- package/dist/components/provider/useHistoryNavigationPatch.d.ts +0 -3
- package/dist/components/provider/useHistoryNavigationPatch.js +0 -47
- package/dist/components/provider/useProviderCache.d.ts +0 -12
- package/dist/components/provider/useProviderCache.js +0 -82
- package/dist/context/AixsterContext.d.ts +0 -3
- package/dist/context/AixsterContext.js +0 -2
- package/dist/context/LangContext.d.ts +0 -1
- package/dist/context/LangContext.js +0 -2
- package/dist/context/LangRoutingContext.d.ts +0 -8
- package/dist/context/LangRoutingContext.js +0 -7
- package/dist/context/LovalingoContext.d.ts +0 -1
- package/dist/context/LovalingoContext.js +0 -1
- package/dist/hooks/provider/useBundleLoading.d.ts +0 -33
- package/dist/hooks/provider/useBundleLoading.js +0 -380
- package/dist/hooks/provider/useDomRules.d.ts +0 -15
- package/dist/hooks/provider/useDomRules.js +0 -38
- package/dist/hooks/provider/useLinkAutoPrefix.d.ts +0 -12
- package/dist/hooks/provider/useLinkAutoPrefix.js +0 -146
- package/dist/hooks/provider/useNavigationPrefetch.d.ts +0 -12
- package/dist/hooks/provider/useNavigationPrefetch.js +0 -82
- package/dist/hooks/provider/usePageviewTracking.d.ts +0 -10
- package/dist/hooks/provider/usePageviewTracking.js +0 -44
- package/dist/hooks/provider/usePrehide.d.ts +0 -5
- package/dist/hooks/provider/usePrehide.js +0 -72
- package/dist/hooks/provider/useSitemapLinkTag.d.ts +0 -7
- package/dist/hooks/provider/useSitemapLinkTag.js +0 -28
- package/dist/hooks/provider/useStringMissReporting.d.ts +0 -14
- package/dist/hooks/provider/useStringMissReporting.js +0 -155
- package/dist/hooks/useAixster.d.ts +0 -6
- package/dist/hooks/useAixster.js +0 -14
- package/dist/hooks/useAixsterEdit.d.ts +0 -5
- package/dist/hooks/useAixsterEdit.js +0 -13
- package/dist/hooks/useAixsterTranslate.d.ts +0 -4
- package/dist/hooks/useAixsterTranslate.js +0 -12
- package/dist/hooks/useLang.d.ts +0 -16
- package/dist/hooks/useLang.js +0 -23
- package/dist/hooks/useLangNavigate.d.ts +0 -24
- package/dist/hooks/useLangNavigate.js +0 -40
- package/dist/hooks/useLovalingo.d.ts +0 -1
- package/dist/hooks/useLovalingo.js +0 -1
- package/dist/hooks/useLovalingoEdit.d.ts +0 -1
- package/dist/hooks/useLovalingoEdit.js +0 -1
- package/dist/hooks/useLovalingoTranslate.d.ts +0 -1
- package/dist/hooks/useLovalingoTranslate.js +0 -1
- package/dist/types.d.ts +0 -76
- package/dist/types.js +0 -1
- package/dist/utils/api.d.ts +0 -42
- package/dist/utils/api.js +0 -395
- package/dist/utils/apiTypes.d.ts +0 -78
- package/dist/utils/apiTypes.js +0 -1
- package/dist/utils/apiUtils.d.ts +0 -4
- package/dist/utils/apiUtils.js +0 -54
- package/dist/utils/domRules.d.ts +0 -2
- package/dist/utils/domRules.js +0 -150
- package/dist/utils/hash.d.ts +0 -9
- package/dist/utils/hash.js +0 -27
- package/dist/utils/languageFlags.d.ts +0 -7
- package/dist/utils/languageFlags.js +0 -90
- package/dist/utils/logger.d.ts +0 -3
- package/dist/utils/logger.js +0 -40
- package/dist/utils/markerEngine.d.ts +0 -12
- package/dist/utils/markerEngine.js +0 -109
- package/dist/utils/markerEngineApply.d.ts +0 -3
- package/dist/utils/markerEngineApply.js +0 -136
- package/dist/utils/markerEngineConstants.d.ts +0 -10
- package/dist/utils/markerEngineConstants.js +0 -12
- package/dist/utils/markerEngineCritical.d.ts +0 -2
- package/dist/utils/markerEngineCritical.js +0 -98
- package/dist/utils/markerEngineDomUtils.d.ts +0 -8
- package/dist/utils/markerEngineDomUtils.js +0 -74
- package/dist/utils/markerEngineFilters.d.ts +0 -2
- package/dist/utils/markerEngineFilters.js +0 -26
- package/dist/utils/markerEngineMisses.d.ts +0 -5
- package/dist/utils/markerEngineMisses.js +0 -81
- package/dist/utils/markerEngineOriginals.d.ts +0 -5
- package/dist/utils/markerEngineOriginals.js +0 -29
- package/dist/utils/markerEngineScan.d.ts +0 -5
- package/dist/utils/markerEngineScan.js +0 -162
- package/dist/utils/markerEngineState.d.ts +0 -4
- package/dist/utils/markerEngineState.js +0 -14
- package/dist/utils/markerEngineStats.d.ts +0 -3
- package/dist/utils/markerEngineStats.js +0 -28
- package/dist/utils/markerEngineTranslations.d.ts +0 -3
- package/dist/utils/markerEngineTranslations.js +0 -49
- package/dist/utils/markerEngineTypes.d.ts +0 -62
- package/dist/utils/markerEngineTypes.js +0 -1
- package/dist/utils/markerEngineViewport.d.ts +0 -2
- package/dist/utils/markerEngineViewport.js +0 -27
- package/dist/utils/mergeEntitlements.d.ts +0 -2
- package/dist/utils/mergeEntitlements.js +0 -7
- package/dist/utils/nonLocalizedPaths.d.ts +0 -12
- package/dist/utils/nonLocalizedPaths.js +0 -136
- package/dist/utils/pathNormalizer.d.ts +0 -49
- package/dist/utils/pathNormalizer.js +0 -115
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/components/provider/providerConstants.ts
|
|
2
|
+
var LOCALE_STORAGE_KEY = "Lovalingo_locale";
|
|
3
|
+
var LOADING_BG_STORAGE_PREFIX = "Lovalingo_loading_bg_color";
|
|
4
|
+
var BRANDING_STORAGE_PREFIX = "Lovalingo_branding_enabled";
|
|
5
|
+
var EDIT_MODE_PARAM = "edit_mode";
|
|
6
|
+
var EDIT_KEY_PARAM = "edit_key";
|
|
7
|
+
var LIVE_MISSES_QUERY_PARAM = "lovalingo_live_misses";
|
|
8
|
+
var DEFAULT_PATH_NORMALIZATION = { enabled: true };
|
|
9
|
+
var EDIT_MODE_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
10
|
+
var EDIT_UI_ATTR = "data-lovalingo-edit-ui";
|
|
11
|
+
var EDIT_HIGHLIGHT_ID = "lovalingo-edit-highlight";
|
|
12
|
+
var EDIT_HINT_ID = "lovalingo-edit-hint";
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
LOCALE_STORAGE_KEY,
|
|
16
|
+
LOADING_BG_STORAGE_PREFIX,
|
|
17
|
+
BRANDING_STORAGE_PREFIX,
|
|
18
|
+
EDIT_MODE_PARAM,
|
|
19
|
+
EDIT_KEY_PARAM,
|
|
20
|
+
LIVE_MISSES_QUERY_PARAM,
|
|
21
|
+
DEFAULT_PATH_NORMALIZATION,
|
|
22
|
+
EDIT_MODE_VALUES,
|
|
23
|
+
EDIT_UI_ATTR,
|
|
24
|
+
EDIT_HIGHLIGHT_ID,
|
|
25
|
+
EDIT_HINT_ID
|
|
26
|
+
};
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LangRoutingContext,
|
|
3
|
+
logDebug
|
|
4
|
+
} from "./chunk-7D5LBV45.mjs";
|
|
5
|
+
import {
|
|
6
|
+
isNonLocalizedPath,
|
|
7
|
+
parseBootstrapInactivePages,
|
|
8
|
+
parseBootstrapNonLocalizedPaths
|
|
9
|
+
} from "./chunk-2FZR2AKF.mjs";
|
|
10
|
+
|
|
11
|
+
// src/components/LangRouter.tsx
|
|
12
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
13
|
+
import { BrowserRouter, Routes, Route, Navigate, Outlet, useLocation, useNavigate } from "react-router-dom";
|
|
14
|
+
|
|
15
|
+
// src/context/LangContext.ts
|
|
16
|
+
import { createContext } from "react";
|
|
17
|
+
var LangContext = createContext(null);
|
|
18
|
+
|
|
19
|
+
// src/components/LangRouter.tsx
|
|
20
|
+
function NavigateExporter({ navigateRef }) {
|
|
21
|
+
const navigate = useNavigate();
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (navigateRef) {
|
|
24
|
+
navigateRef.current = navigate;
|
|
25
|
+
}
|
|
26
|
+
}, [navigate, navigateRef]);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function LangGuard({
|
|
30
|
+
lang,
|
|
31
|
+
nonLocalizedPaths,
|
|
32
|
+
defaultLang
|
|
33
|
+
}) {
|
|
34
|
+
const location = useLocation();
|
|
35
|
+
const prefix = `/${lang}`;
|
|
36
|
+
const restPath = location.pathname.startsWith(prefix) ? location.pathname.slice(prefix.length) || "/" : location.pathname;
|
|
37
|
+
if (isNonLocalizedPath(restPath, nonLocalizedPaths)) {
|
|
38
|
+
const nextPath = `${restPath}${location.search}${location.hash}`;
|
|
39
|
+
return /* @__PURE__ */ React.createElement(Navigate, { to: nextPath, replace: true });
|
|
40
|
+
}
|
|
41
|
+
return /* @__PURE__ */ React.createElement(LangContext.Provider, { value: lang }, /* @__PURE__ */ React.createElement(Outlet, { context: { lang } }));
|
|
42
|
+
}
|
|
43
|
+
function RedirectToDefaultLang({
|
|
44
|
+
defaultLang,
|
|
45
|
+
children,
|
|
46
|
+
nonLocalizedPaths,
|
|
47
|
+
routingStatus
|
|
48
|
+
}) {
|
|
49
|
+
const location = useLocation();
|
|
50
|
+
const navigate = useNavigate();
|
|
51
|
+
const shouldSkip = isNonLocalizedPath(location.pathname, nonLocalizedPaths);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (shouldSkip) return;
|
|
54
|
+
if (routingStatus === "loading") return;
|
|
55
|
+
const nextPath = location.pathname === "/" || location.pathname === "" ? `/${defaultLang}${location.search}${location.hash}` : `/${defaultLang}${location.pathname}${location.search}${location.hash}`;
|
|
56
|
+
const current = `${location.pathname}${location.search}${location.hash}`;
|
|
57
|
+
if (nextPath === current) return;
|
|
58
|
+
navigate(nextPath, { replace: true });
|
|
59
|
+
}, [defaultLang, location.hash, location.pathname, location.search, navigate, routingStatus, shouldSkip]);
|
|
60
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
|
|
61
|
+
}
|
|
62
|
+
function LangRouter({ children, defaultLang, langs, navigateRef, apiBase, apiKey, publicAnonKey }) {
|
|
63
|
+
const metaKey = typeof document !== "undefined" ? document.querySelector('meta[name="lovalingo-public-anon-key"]')?.content?.trim() || "" : "";
|
|
64
|
+
const globals = globalThis;
|
|
65
|
+
const resolvedApiKey = (typeof apiKey === "string" && apiKey.trim().length > 0 ? apiKey : typeof publicAnonKey === "string" && publicAnonKey.trim().length > 0 ? publicAnonKey : globals.__LOVALINGO_PUBLIC_ANON_KEY__ || globals.__LOVALINGO_API_KEY__ || metaKey || "").trim();
|
|
66
|
+
const resolvedApiBase = typeof apiBase === "string" && apiBase.trim().length > 0 ? apiBase.trim() : "https://cdn.lovalingo.com";
|
|
67
|
+
const nonLocalizedStorageKey = useMemo(
|
|
68
|
+
() => `Lovalingo_non_localized_paths:${resolvedApiKey || "anonymous"}`,
|
|
69
|
+
[resolvedApiKey]
|
|
70
|
+
);
|
|
71
|
+
const inactivePagesStorageKey = useMemo(
|
|
72
|
+
() => `Lovalingo_inactive_pages:${resolvedApiKey || "anonymous"}`,
|
|
73
|
+
[resolvedApiKey]
|
|
74
|
+
);
|
|
75
|
+
const [nonLocalizedPaths, setNonLocalizedPaths] = useState(() => {
|
|
76
|
+
if (typeof window === "undefined") return [];
|
|
77
|
+
if (!resolvedApiKey) return [];
|
|
78
|
+
try {
|
|
79
|
+
const raw = localStorage.getItem(nonLocalizedStorageKey);
|
|
80
|
+
if (!raw) return [];
|
|
81
|
+
const parsed = JSON.parse(raw);
|
|
82
|
+
return parseBootstrapNonLocalizedPaths(parsed);
|
|
83
|
+
} catch {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const [inactivePages, setInactivePages] = useState(() => {
|
|
88
|
+
if (typeof window === "undefined") return [];
|
|
89
|
+
if (!resolvedApiKey) return [];
|
|
90
|
+
try {
|
|
91
|
+
const raw = localStorage.getItem(inactivePagesStorageKey);
|
|
92
|
+
if (!raw) return [];
|
|
93
|
+
const parsed = JSON.parse(raw);
|
|
94
|
+
return parseBootstrapInactivePages(parsed);
|
|
95
|
+
} catch {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const [routingStatus, setRoutingStatus] = useState(() => {
|
|
100
|
+
if (!resolvedApiKey) return "unknown";
|
|
101
|
+
return nonLocalizedPaths.length > 0 || inactivePages.length > 0 ? "ready" : "loading";
|
|
102
|
+
});
|
|
103
|
+
const fetchRoutingConfig = useCallback(async () => {
|
|
104
|
+
if (typeof window === "undefined") return;
|
|
105
|
+
if (!resolvedApiKey) return;
|
|
106
|
+
const pathParam = window.location.pathname + window.location.search;
|
|
107
|
+
const requestUrl = `${resolvedApiBase}/functions/v1/bootstrap?key=${encodeURIComponent(resolvedApiKey)}&locale=${encodeURIComponent(defaultLang)}&path=${encodeURIComponent(pathParam)}`;
|
|
108
|
+
const response = await fetch(requestUrl);
|
|
109
|
+
const resolvedResponse = response.status === 304 ? await fetch(requestUrl, { cache: "force-cache" }) : response;
|
|
110
|
+
if (!resolvedResponse.ok) throw new Error(`bootstrap HTTP ${resolvedResponse.status}`);
|
|
111
|
+
const data = await resolvedResponse.json();
|
|
112
|
+
const record = data || {};
|
|
113
|
+
return {
|
|
114
|
+
nonLocalizedPaths: parseBootstrapNonLocalizedPaths(record["non_localized_paths"]),
|
|
115
|
+
inactivePages: parseBootstrapInactivePages(record["inactive_pages"])
|
|
116
|
+
};
|
|
117
|
+
}, [defaultLang, resolvedApiBase, resolvedApiKey]);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
let cancelled = false;
|
|
120
|
+
void (async () => {
|
|
121
|
+
if (!resolvedApiKey) return;
|
|
122
|
+
setRoutingStatus((prev) => prev === "ready" ? prev : "loading");
|
|
123
|
+
try {
|
|
124
|
+
const next = await fetchRoutingConfig();
|
|
125
|
+
if (cancelled || !next) return;
|
|
126
|
+
setNonLocalizedPaths(next.nonLocalizedPaths);
|
|
127
|
+
setInactivePages(next.inactivePages);
|
|
128
|
+
setRoutingStatus("ready");
|
|
129
|
+
try {
|
|
130
|
+
localStorage.setItem(nonLocalizedStorageKey, JSON.stringify(next.nonLocalizedPaths));
|
|
131
|
+
localStorage.setItem(inactivePagesStorageKey, JSON.stringify(next.inactivePages));
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
} catch (err) {
|
|
135
|
+
if (cancelled) return;
|
|
136
|
+
setRoutingStatus("error");
|
|
137
|
+
logDebug("[Lovalingo] Failed to fetch routing config:", err);
|
|
138
|
+
}
|
|
139
|
+
})();
|
|
140
|
+
return () => {
|
|
141
|
+
cancelled = true;
|
|
142
|
+
};
|
|
143
|
+
}, [fetchRoutingConfig, inactivePagesStorageKey, nonLocalizedStorageKey, resolvedApiKey]);
|
|
144
|
+
return /* @__PURE__ */ React.createElement(BrowserRouter, null, /* @__PURE__ */ React.createElement(NavigateExporter, { navigateRef }), /* @__PURE__ */ React.createElement(LangRoutingContext.Provider, { value: { defaultLang, nonLocalizedPaths, inactivePages, status: routingStatus } }, /* @__PURE__ */ React.createElement(Routes, null, langs.map((lang) => /* @__PURE__ */ React.createElement(
|
|
145
|
+
Route,
|
|
146
|
+
{
|
|
147
|
+
key: lang,
|
|
148
|
+
path: `${lang}/*`,
|
|
149
|
+
element: /* @__PURE__ */ React.createElement(LangGuard, { lang, nonLocalizedPaths, defaultLang })
|
|
150
|
+
},
|
|
151
|
+
/* @__PURE__ */ React.createElement(Route, { index: true, element: /* @__PURE__ */ React.createElement(React.Fragment, null, children) }),
|
|
152
|
+
/* @__PURE__ */ React.createElement(Route, { path: "*", element: /* @__PURE__ */ React.createElement(React.Fragment, null, children) })
|
|
153
|
+
)), /* @__PURE__ */ React.createElement(
|
|
154
|
+
Route,
|
|
155
|
+
{
|
|
156
|
+
path: "*",
|
|
157
|
+
element: /* @__PURE__ */ React.createElement(
|
|
158
|
+
RedirectToDefaultLang,
|
|
159
|
+
{
|
|
160
|
+
defaultLang,
|
|
161
|
+
nonLocalizedPaths,
|
|
162
|
+
routingStatus
|
|
163
|
+
},
|
|
164
|
+
children
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
))));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/components/LangLink.tsx
|
|
171
|
+
import React2 from "react";
|
|
172
|
+
import { Link } from "react-router-dom";
|
|
173
|
+
|
|
174
|
+
// src/hooks/useLang.ts
|
|
175
|
+
import { useParams } from "react-router-dom";
|
|
176
|
+
import { useContext } from "react";
|
|
177
|
+
function useLang() {
|
|
178
|
+
const ctxLang = useContext(LangContext);
|
|
179
|
+
const { lang } = useParams();
|
|
180
|
+
return ctxLang ?? lang ?? "en";
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/components/LangLink.tsx
|
|
184
|
+
import { useContext as useContext2 } from "react";
|
|
185
|
+
function LangLink({ to, ...props }) {
|
|
186
|
+
const lang = useLang();
|
|
187
|
+
const routing = useContext2(LangRoutingContext);
|
|
188
|
+
const langTo = typeof to === "string" ? (() => {
|
|
189
|
+
const trimmed = (to || "").toString().trim();
|
|
190
|
+
const normalized = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
191
|
+
return isNonLocalizedPath(normalized, routing.nonLocalizedPaths) ? normalized : `/${lang}${normalized}`;
|
|
192
|
+
})() : to;
|
|
193
|
+
return /* @__PURE__ */ React2.createElement(Link, { ...props, to: langTo });
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// src/hooks/useLangNavigate.ts
|
|
197
|
+
import { useNavigate as useNavigate2 } from "react-router-dom";
|
|
198
|
+
import { useCallback as useCallback2, useContext as useContext3 } from "react";
|
|
199
|
+
function useLangNavigate() {
|
|
200
|
+
const navigate = useNavigate2();
|
|
201
|
+
const lang = useLang();
|
|
202
|
+
const routing = useContext3(LangRoutingContext);
|
|
203
|
+
return useCallback2(
|
|
204
|
+
(path, options) => {
|
|
205
|
+
const trimmed = (path || "").toString().trim();
|
|
206
|
+
if (!trimmed) return;
|
|
207
|
+
const normalized = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
208
|
+
const fullPath = isNonLocalizedPath(normalized, routing.nonLocalizedPaths) ? normalized : `/${lang}${normalized}`;
|
|
209
|
+
navigate(fullPath, options);
|
|
210
|
+
},
|
|
211
|
+
[lang, navigate, routing.nonLocalizedPaths]
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export {
|
|
216
|
+
LangRouter,
|
|
217
|
+
useLang,
|
|
218
|
+
LangLink,
|
|
219
|
+
useLangNavigate
|
|
220
|
+
};
|
package/dist/core.d.mts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Path Normalization Utility
|
|
5
|
+
*
|
|
6
|
+
* Normalizes URL paths by replacing dynamic segments (UUIDs, IDs, slugs)
|
|
7
|
+
* with placeholders to enable translation bundle sharing across similar pages.
|
|
8
|
+
*
|
|
9
|
+
* Example:
|
|
10
|
+
* /dashboard/projects/4458eb10-608c-4622-a92e-ec3ed2eeb524/setup
|
|
11
|
+
* → /dashboard/projects/:id/setup
|
|
12
|
+
*/
|
|
13
|
+
interface PathNormalizationRule {
|
|
14
|
+
pattern: string;
|
|
15
|
+
replacement: string;
|
|
16
|
+
includeSubpaths?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface PathNormalizationConfig {
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
rules?: PathNormalizationRule[];
|
|
21
|
+
supportedLocales?: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface LovalingoConfig {
|
|
25
|
+
/**
|
|
26
|
+
* Public project key (safe to expose in the browser).
|
|
27
|
+
*/
|
|
28
|
+
publicAnonKey?: string;
|
|
29
|
+
apiKey?: string;
|
|
30
|
+
defaultLocale: string;
|
|
31
|
+
locales: string[];
|
|
32
|
+
apiBase?: string;
|
|
33
|
+
routing?: 'query' | 'path';
|
|
34
|
+
autoPrefixLinks?: boolean;
|
|
35
|
+
overlayBgColor?: string;
|
|
36
|
+
switcherPosition?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
37
|
+
switcherOffsetY?: number;
|
|
38
|
+
switcherTheme?: 'dark' | 'light';
|
|
39
|
+
editMode?: boolean;
|
|
40
|
+
editKey?: string;
|
|
41
|
+
pathNormalization?: PathNormalizationConfig;
|
|
42
|
+
mode?: 'dom';
|
|
43
|
+
autoApplyRules?: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface LovalingoContextValue {
|
|
46
|
+
locale: string;
|
|
47
|
+
setLocale: (locale: string) => void;
|
|
48
|
+
isLoading: boolean;
|
|
49
|
+
translationMap: Record<string, string>;
|
|
50
|
+
config: LovalingoConfig;
|
|
51
|
+
translateElement: (element: HTMLElement) => void;
|
|
52
|
+
translateDOM: () => void;
|
|
53
|
+
editMode: boolean;
|
|
54
|
+
toggleEditMode: () => void;
|
|
55
|
+
excludeElement: (selector: string) => Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
interface Translation {
|
|
58
|
+
source_text: string;
|
|
59
|
+
translated_text: string;
|
|
60
|
+
source_locale: string;
|
|
61
|
+
target_locale: string;
|
|
62
|
+
content_hash?: string;
|
|
63
|
+
}
|
|
64
|
+
interface Exclusion {
|
|
65
|
+
selector: string;
|
|
66
|
+
type: 'css' | 'xpath';
|
|
67
|
+
}
|
|
68
|
+
type DomRuleType = 'replace_text' | 'set_attribute' | 'set_html' | 'add_class' | 'remove' | 'css' | 'script';
|
|
69
|
+
interface DomRule {
|
|
70
|
+
id: string;
|
|
71
|
+
rule_type: DomRuleType;
|
|
72
|
+
selector?: string | null;
|
|
73
|
+
page_path?: string | null;
|
|
74
|
+
locale?: string | null;
|
|
75
|
+
payload?: {
|
|
76
|
+
matchText?: string;
|
|
77
|
+
text?: string;
|
|
78
|
+
attribute?: string;
|
|
79
|
+
value?: string;
|
|
80
|
+
html?: string;
|
|
81
|
+
className?: string;
|
|
82
|
+
css?: string;
|
|
83
|
+
script?: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface LovalingoProviderProps extends LovalingoConfig {
|
|
88
|
+
children: React.ReactNode;
|
|
89
|
+
sitemap?: boolean;
|
|
90
|
+
seo?: boolean;
|
|
91
|
+
navigateRef?: React.MutableRefObject<((path: string) => void) | undefined>;
|
|
92
|
+
}
|
|
93
|
+
declare const LovalingoProvider: React.FC<LovalingoProviderProps>;
|
|
94
|
+
|
|
95
|
+
interface LanguageSwitcherProps {
|
|
96
|
+
locales: string[];
|
|
97
|
+
currentLocale: string;
|
|
98
|
+
onLocaleChange: (locale: string) => void;
|
|
99
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
100
|
+
offsetY?: number;
|
|
101
|
+
theme?: 'dark' | 'light';
|
|
102
|
+
branding?: {
|
|
103
|
+
required?: boolean;
|
|
104
|
+
enabled?: boolean;
|
|
105
|
+
label?: string;
|
|
106
|
+
href?: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
declare const LanguageSwitcher: React.FC<LanguageSwitcherProps>;
|
|
110
|
+
|
|
111
|
+
declare const useLovalingo: () => {
|
|
112
|
+
locale: string;
|
|
113
|
+
setLocale: (locale: string) => void;
|
|
114
|
+
isLoading: boolean;
|
|
115
|
+
config: LovalingoConfig;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
declare const useLovalingoTranslate: () => {
|
|
119
|
+
translateElement: (element: HTMLElement) => void;
|
|
120
|
+
translateDOM: () => void;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
declare const useLovalingoEdit: () => {
|
|
124
|
+
editMode: boolean;
|
|
125
|
+
toggleEditMode: () => void;
|
|
126
|
+
excludeElement: (selector: string) => Promise<void>;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
declare const VERSION = "0.6.0";
|
|
130
|
+
|
|
131
|
+
export { type DomRule, type DomRuleType, type Exclusion, LanguageSwitcher, type LovalingoConfig, type LovalingoContextValue, LovalingoProvider, type Translation, VERSION, useLovalingo, useLovalingoEdit, useLovalingoTranslate };
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Path Normalization Utility
|
|
5
|
+
*
|
|
6
|
+
* Normalizes URL paths by replacing dynamic segments (UUIDs, IDs, slugs)
|
|
7
|
+
* with placeholders to enable translation bundle sharing across similar pages.
|
|
8
|
+
*
|
|
9
|
+
* Example:
|
|
10
|
+
* /dashboard/projects/4458eb10-608c-4622-a92e-ec3ed2eeb524/setup
|
|
11
|
+
* → /dashboard/projects/:id/setup
|
|
12
|
+
*/
|
|
13
|
+
interface PathNormalizationRule {
|
|
14
|
+
pattern: string;
|
|
15
|
+
replacement: string;
|
|
16
|
+
includeSubpaths?: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface PathNormalizationConfig {
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
rules?: PathNormalizationRule[];
|
|
21
|
+
supportedLocales?: string[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface LovalingoConfig {
|
|
25
|
+
/**
|
|
26
|
+
* Public project key (safe to expose in the browser).
|
|
27
|
+
*/
|
|
28
|
+
publicAnonKey?: string;
|
|
29
|
+
apiKey?: string;
|
|
30
|
+
defaultLocale: string;
|
|
31
|
+
locales: string[];
|
|
32
|
+
apiBase?: string;
|
|
33
|
+
routing?: 'query' | 'path';
|
|
34
|
+
autoPrefixLinks?: boolean;
|
|
35
|
+
overlayBgColor?: string;
|
|
36
|
+
switcherPosition?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
37
|
+
switcherOffsetY?: number;
|
|
38
|
+
switcherTheme?: 'dark' | 'light';
|
|
39
|
+
editMode?: boolean;
|
|
40
|
+
editKey?: string;
|
|
41
|
+
pathNormalization?: PathNormalizationConfig;
|
|
42
|
+
mode?: 'dom';
|
|
43
|
+
autoApplyRules?: boolean;
|
|
44
|
+
}
|
|
45
|
+
interface LovalingoContextValue {
|
|
46
|
+
locale: string;
|
|
47
|
+
setLocale: (locale: string) => void;
|
|
48
|
+
isLoading: boolean;
|
|
49
|
+
translationMap: Record<string, string>;
|
|
50
|
+
config: LovalingoConfig;
|
|
51
|
+
translateElement: (element: HTMLElement) => void;
|
|
52
|
+
translateDOM: () => void;
|
|
53
|
+
editMode: boolean;
|
|
54
|
+
toggleEditMode: () => void;
|
|
55
|
+
excludeElement: (selector: string) => Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
interface Translation {
|
|
58
|
+
source_text: string;
|
|
59
|
+
translated_text: string;
|
|
60
|
+
source_locale: string;
|
|
61
|
+
target_locale: string;
|
|
62
|
+
content_hash?: string;
|
|
63
|
+
}
|
|
64
|
+
interface Exclusion {
|
|
65
|
+
selector: string;
|
|
66
|
+
type: 'css' | 'xpath';
|
|
67
|
+
}
|
|
68
|
+
type DomRuleType = 'replace_text' | 'set_attribute' | 'set_html' | 'add_class' | 'remove' | 'css' | 'script';
|
|
69
|
+
interface DomRule {
|
|
70
|
+
id: string;
|
|
71
|
+
rule_type: DomRuleType;
|
|
72
|
+
selector?: string | null;
|
|
73
|
+
page_path?: string | null;
|
|
74
|
+
locale?: string | null;
|
|
75
|
+
payload?: {
|
|
76
|
+
matchText?: string;
|
|
77
|
+
text?: string;
|
|
78
|
+
attribute?: string;
|
|
79
|
+
value?: string;
|
|
80
|
+
html?: string;
|
|
81
|
+
className?: string;
|
|
82
|
+
css?: string;
|
|
83
|
+
script?: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface LovalingoProviderProps extends LovalingoConfig {
|
|
88
|
+
children: React.ReactNode;
|
|
89
|
+
sitemap?: boolean;
|
|
90
|
+
seo?: boolean;
|
|
91
|
+
navigateRef?: React.MutableRefObject<((path: string) => void) | undefined>;
|
|
92
|
+
}
|
|
93
|
+
declare const LovalingoProvider: React.FC<LovalingoProviderProps>;
|
|
94
|
+
|
|
95
|
+
interface LanguageSwitcherProps {
|
|
96
|
+
locales: string[];
|
|
97
|
+
currentLocale: string;
|
|
98
|
+
onLocaleChange: (locale: string) => void;
|
|
99
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
100
|
+
offsetY?: number;
|
|
101
|
+
theme?: 'dark' | 'light';
|
|
102
|
+
branding?: {
|
|
103
|
+
required?: boolean;
|
|
104
|
+
enabled?: boolean;
|
|
105
|
+
label?: string;
|
|
106
|
+
href?: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
declare const LanguageSwitcher: React.FC<LanguageSwitcherProps>;
|
|
110
|
+
|
|
111
|
+
declare const useLovalingo: () => {
|
|
112
|
+
locale: string;
|
|
113
|
+
setLocale: (locale: string) => void;
|
|
114
|
+
isLoading: boolean;
|
|
115
|
+
config: LovalingoConfig;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
declare const useLovalingoTranslate: () => {
|
|
119
|
+
translateElement: (element: HTMLElement) => void;
|
|
120
|
+
translateDOM: () => void;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
declare const useLovalingoEdit: () => {
|
|
124
|
+
editMode: boolean;
|
|
125
|
+
toggleEditMode: () => void;
|
|
126
|
+
excludeElement: (selector: string) => Promise<void>;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
declare const VERSION = "0.6.0";
|
|
130
|
+
|
|
131
|
+
export { type DomRule, type DomRuleType, type Exclusion, LanguageSwitcher, type LovalingoConfig, type LovalingoContextValue, LovalingoProvider, type Translation, VERSION, useLovalingo, useLovalingoEdit, useLovalingoTranslate };
|