@translation-cms/sync 1.1.59 → 1.1.60
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 +24 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/translation-provider.d.ts +23 -0
- package/dist/translation-provider.d.ts.map +1 -0
- package/dist/translation-provider.js +95 -0
- package/dist/translation-provider.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
# React TranslationProvider
|
|
2
|
+
|
|
3
|
+
Wrap je app of componenten met de TranslationProvider om i18n context te
|
|
4
|
+
leveren:
|
|
5
|
+
|
|
6
|
+
```tsx
|
|
7
|
+
import { TranslationProvider } from '@translation-cms/sync';
|
|
8
|
+
|
|
9
|
+
export default function RootLayout({
|
|
10
|
+
children,
|
|
11
|
+
}: {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
}) {
|
|
14
|
+
return <TranslationProvider locale="nl">{children}</TranslationProvider>;
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
De provider initialiseert i18n en zorgt dat de context beschikbaar is voor alle
|
|
19
|
+
onderliggende componenten.
|
|
20
|
+
|
|
1
21
|
# @translation-cms/sync
|
|
2
22
|
|
|
3
23
|
Automatically scan translation keys in your codebase and sync them to the
|
|
@@ -39,7 +59,10 @@ root. Values here are merged with env vars — CLI args take highest priority.
|
|
|
39
59
|
"reservedCssNamespaces": ["after", "before"],
|
|
40
60
|
"previewRoutes": {
|
|
41
61
|
"namespace:key": [
|
|
42
|
-
{
|
|
62
|
+
{
|
|
63
|
+
"route": "/[locale]/blog/[slug]",
|
|
64
|
+
"params": { "slug": "first-post" }
|
|
65
|
+
}
|
|
43
66
|
]
|
|
44
67
|
}
|
|
45
68
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { TranslationProvider, type TranslationProviderProps, } from './translation-provider.js';
|
|
1
2
|
export { CMSClient, getCMSClient, type CMSConfig, type TranslationResponse, type NamespacedTranslations, } from './client.js';
|
|
2
3
|
export { initPreviewListener, cleanupPreviewListener, type PreviewListenerOptions, } from './preview-listener.js';
|
|
3
4
|
export { type TranslationsConfig } from './config.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,SAAS,EACT,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,GAC9B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACH,mBAAmB,EACnB,KAAK,wBAAwB,GAChC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACH,SAAS,EACT,YAAY,EACZ,KAAK,SAAS,EACd,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,GAC9B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtD,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,GACnB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,OAAO,EACH,SAAS,EACT,YAAY,GAIf,MAAM,aAAa,CAAC;AAErB,kCAAkC;AAClC,OAAO,EACH,mBAAmB,EACnB,sBAAsB,GAEzB,MAAM,uBAAuB,CAAC;AAK/B,6CAA6C;AAC7C,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,SAAS,GAIZ,MAAM,cAAc,CAAC;AAEtB,oDAAoD;AACpD,OAAO,EAAE,UAAU,EAA0B,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EACH,mBAAmB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,4BAA4B;AAC5B,OAAO,EACH,SAAS,EACT,YAAY,GAIf,MAAM,aAAa,CAAC;AAErB,kCAAkC;AAClC,OAAO,EACH,mBAAmB,EACnB,sBAAsB,GAEzB,MAAM,uBAAuB,CAAC;AAK/B,6CAA6C;AAC7C,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,SAAS,GAIZ,MAAM,cAAc,CAAC;AAEtB,oDAAoD;AACpD,OAAO,EAAE,UAAU,EAA0B,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getCMSClient } from './client.js';
|
|
3
|
+
import type { TOptions, TranslationResponse } from './client.js';
|
|
4
|
+
export interface TranslationProviderProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
locale: string;
|
|
7
|
+
namespaces?: string[];
|
|
8
|
+
/**
|
|
9
|
+
* Optionally override CMS config (for multi-project setups)
|
|
10
|
+
*/
|
|
11
|
+
config?: Parameters<typeof getCMSClient>[0];
|
|
12
|
+
}
|
|
13
|
+
interface TranslationContextValue {
|
|
14
|
+
t: (key: string, options?: TOptions) => string;
|
|
15
|
+
tDynamic: (key: string, options?: TOptions) => string;
|
|
16
|
+
isLoading: boolean;
|
|
17
|
+
locale: string;
|
|
18
|
+
translations: TranslationResponse;
|
|
19
|
+
}
|
|
20
|
+
export declare function TranslationProvider({ children, locale, namespaces, config, }: TranslationProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function useTranslationContext(): TranslationContextValue;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=translation-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-provider.d.ts","sourceRoot":"","sources":["../src/translation-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEjE,MAAM,WAAW,wBAAwB;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;CAC/C;AAGD,UAAU,uBAAuB;IAC7B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,KAAK,MAAM,CAAC;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,KAAK,MAAM,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,mBAAmB,CAAC;CACrC;AAMD,wBAAgB,mBAAmB,CAAC,EAChC,QAAQ,EACR,MAAM,EACN,UAAuB,EACvB,MAAM,GACT,EAAE,wBAAwB,2CA6G1B;AAGD,wBAAgB,qBAAqB,4BAOpC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useEffect, useState, useMemo, } from 'react';
|
|
3
|
+
import { getCMSClient } from './client.js';
|
|
4
|
+
const TranslationContext = createContext(undefined);
|
|
5
|
+
export function TranslationProvider({ children, locale, namespaces = ['common'], config, }) {
|
|
6
|
+
// Compose a key from dependencies to reset loading state
|
|
7
|
+
const depsKey = useMemo(() => [locale, JSON.stringify(namespaces), JSON.stringify(config)].join('|'), [locale, namespaces, config]);
|
|
8
|
+
const [state, setState] = useState(() => ({
|
|
9
|
+
isLoading: true,
|
|
10
|
+
translations: {},
|
|
11
|
+
depsKey,
|
|
12
|
+
}));
|
|
13
|
+
// Reset loading state when depsKey changes
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (state.depsKey !== depsKey) {
|
|
16
|
+
setState({ isLoading: true, translations: {}, depsKey });
|
|
17
|
+
}
|
|
18
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
19
|
+
}, [depsKey]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (state.depsKey !== depsKey)
|
|
22
|
+
return;
|
|
23
|
+
let cancelled = false;
|
|
24
|
+
const client = getCMSClient(config);
|
|
25
|
+
client
|
|
26
|
+
.getTranslations(namespaces, locale)
|
|
27
|
+
.then((data) => {
|
|
28
|
+
if (!cancelled) {
|
|
29
|
+
setState({ isLoading: false, translations: data, depsKey });
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return () => {
|
|
33
|
+
cancelled = true;
|
|
34
|
+
};
|
|
35
|
+
}, [depsKey, config, namespaces, locale, state.depsKey]);
|
|
36
|
+
// Plural/variable interpolation logic (mirrors use-translation.ts)
|
|
37
|
+
const resolveTranslation = useMemo(() => {
|
|
38
|
+
return (key, options) => {
|
|
39
|
+
// Plural key selection: try count-specific suffix first
|
|
40
|
+
let resolvedKey = key;
|
|
41
|
+
if (options && typeof options.count === 'number') {
|
|
42
|
+
const count = options.count;
|
|
43
|
+
const suffix = count === 0 ? '_zero' : count === 1 ? '_one' : '_other';
|
|
44
|
+
const pluralKey = `${key}${suffix}`;
|
|
45
|
+
if (pluralKey in state.translations) {
|
|
46
|
+
resolvedKey = pluralKey;
|
|
47
|
+
}
|
|
48
|
+
else if (`${key}_other` in state.translations) {
|
|
49
|
+
resolvedKey = `${key}_other`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let value;
|
|
53
|
+
if (resolvedKey in state.translations) {
|
|
54
|
+
value = state.translations[resolvedKey];
|
|
55
|
+
}
|
|
56
|
+
else if (key in state.translations) {
|
|
57
|
+
value = state.translations[key];
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
value = options?.defaultValue ?? key;
|
|
61
|
+
}
|
|
62
|
+
// Interpolate {{variable}} placeholders (i18next default format)
|
|
63
|
+
if (options) {
|
|
64
|
+
value = value.replace(/\{\{(\w+)\}\}/g, (_, varKey) => varKey in options
|
|
65
|
+
? String(options[varKey])
|
|
66
|
+
: `{{${varKey}}}`);
|
|
67
|
+
}
|
|
68
|
+
return value;
|
|
69
|
+
};
|
|
70
|
+
}, [state.translations]);
|
|
71
|
+
const t = useMemo(() => (key, options) => resolveTranslation(key, options), [resolveTranslation]);
|
|
72
|
+
const tDynamic = t; // identical for now
|
|
73
|
+
const contextValue = useMemo(() => ({
|
|
74
|
+
t,
|
|
75
|
+
tDynamic,
|
|
76
|
+
isLoading: state.isLoading,
|
|
77
|
+
locale,
|
|
78
|
+
translations: state.translations,
|
|
79
|
+
}), [t, tDynamic, state.isLoading, locale, state.translations]);
|
|
80
|
+
// Set <html lang="..."> for accessibility
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (typeof document !== 'undefined') {
|
|
83
|
+
document.documentElement.lang = locale;
|
|
84
|
+
}
|
|
85
|
+
}, [locale]);
|
|
86
|
+
return (_jsx(TranslationContext.Provider, { value: contextValue, children: children }));
|
|
87
|
+
}
|
|
88
|
+
// Consumer hook
|
|
89
|
+
export function useTranslationContext() {
|
|
90
|
+
const ctx = useContext(TranslationContext);
|
|
91
|
+
if (!ctx)
|
|
92
|
+
throw new Error('useTranslationContext must be used within a TranslationProvider');
|
|
93
|
+
return ctx;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=translation-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translation-provider.js","sourceRoot":"","sources":["../src/translation-provider.tsx"],"names":[],"mappings":"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"}
|