@belocal/react 0.1.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 +190 -0
- package/dist/index.cjs +74 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# @belocal/react
|
|
2
|
+
|
|
3
|
+
React SDK for Belocal translation service. Provides easy-to-use React components and hooks for translating your application content.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @belocal/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
### 1. Wrap your app with BelocalProvider
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { BelocalProvider } from '@belocal/react';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return (
|
|
20
|
+
<BelocalProvider
|
|
21
|
+
apiKey="your-api-key"
|
|
22
|
+
defaultLang="en"
|
|
23
|
+
baseUrl="https://api.belocal.dev" // optional
|
|
24
|
+
>
|
|
25
|
+
<YourApp />
|
|
26
|
+
</BelocalProvider>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Use the Translate component
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { Translate } from '@belocal/react';
|
|
35
|
+
|
|
36
|
+
function Welcome() {
|
|
37
|
+
return (
|
|
38
|
+
<div>
|
|
39
|
+
<h1>
|
|
40
|
+
<Translate
|
|
41
|
+
text="Welcome to our app!"
|
|
42
|
+
fallback="Loading..."
|
|
43
|
+
/>
|
|
44
|
+
</h1>
|
|
45
|
+
|
|
46
|
+
<p>
|
|
47
|
+
<Translate
|
|
48
|
+
text="Hello {name}!"
|
|
49
|
+
ctx={{ name: "John" }}
|
|
50
|
+
lang="es" // Override default language
|
|
51
|
+
/>
|
|
52
|
+
</p>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Use the useBelocal hook
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { useBelocal } from '@belocal/react';
|
|
62
|
+
|
|
63
|
+
function CustomTranslation() {
|
|
64
|
+
const { engine, defaultLang } = useBelocal();
|
|
65
|
+
const [translation, setTranslation] = useState('');
|
|
66
|
+
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
engine.t('Hello world!', defaultLang)
|
|
69
|
+
.then(setTranslation)
|
|
70
|
+
.catch(console.error);
|
|
71
|
+
}, [engine, defaultLang]);
|
|
72
|
+
|
|
73
|
+
return <span>{translation}</span>;
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## API Reference
|
|
78
|
+
|
|
79
|
+
### BelocalProvider
|
|
80
|
+
|
|
81
|
+
The root provider component that initializes the Belocal engine.
|
|
82
|
+
|
|
83
|
+
#### Props
|
|
84
|
+
|
|
85
|
+
| Prop | Type | Required | Description |
|
|
86
|
+
|------|------|----------|-------------|
|
|
87
|
+
| `apiKey` | `string` | ✅ | Your Belocal API key |
|
|
88
|
+
| `baseUrl` | `string` | ❌ | Custom API base URL |
|
|
89
|
+
| `defaultLang` | `string` | ❌ | Default language for translations |
|
|
90
|
+
| `children` | `React.ReactNode` | ✅ | Child components |
|
|
91
|
+
|
|
92
|
+
### Translate
|
|
93
|
+
|
|
94
|
+
Component for displaying translated text.
|
|
95
|
+
|
|
96
|
+
#### Props
|
|
97
|
+
|
|
98
|
+
| Prop | Type | Required | Description |
|
|
99
|
+
|------|------|----------|-------------|
|
|
100
|
+
| `text` | `string` | ✅ | Text to translate |
|
|
101
|
+
| `lang` | `string` | ❌ | Target language (overrides defaultLang) |
|
|
102
|
+
| `ctx` | `Record<string, any>` | ❌ | Context variables for interpolation |
|
|
103
|
+
| `fallback` | `string` | ❌ | Text to show while loading |
|
|
104
|
+
|
|
105
|
+
#### Language Priority
|
|
106
|
+
|
|
107
|
+
The language selection follows this priority:
|
|
108
|
+
1. `lang` prop (highest priority)
|
|
109
|
+
2. `defaultLang` from BelocalProvider
|
|
110
|
+
3. No translation if neither is provided
|
|
111
|
+
|
|
112
|
+
### useBelocal
|
|
113
|
+
|
|
114
|
+
Hook for accessing the Belocal engine and configuration.
|
|
115
|
+
|
|
116
|
+
#### Returns
|
|
117
|
+
|
|
118
|
+
| Property | Type | Description |
|
|
119
|
+
|----------|------|-------------|
|
|
120
|
+
| `engine` | `BelocalEngine` | Belocal engine instance |
|
|
121
|
+
| `defaultLang` | `string \| undefined` | Default language from provider |
|
|
122
|
+
|
|
123
|
+
#### Throws
|
|
124
|
+
|
|
125
|
+
- Error if used outside of `BelocalProvider`
|
|
126
|
+
|
|
127
|
+
## Error Handling
|
|
128
|
+
|
|
129
|
+
- **Network errors**: Component falls back to original text
|
|
130
|
+
- **Missing provider**: `useBelocal` throws an error
|
|
131
|
+
- **Invalid context**: Console error, falls back to original text
|
|
132
|
+
|
|
133
|
+
## TypeScript Support
|
|
134
|
+
|
|
135
|
+
Full TypeScript support with exported types:
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import type {
|
|
139
|
+
BelocalProviderProps,
|
|
140
|
+
TranslateProps
|
|
141
|
+
} from '@belocal/react';
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Examples
|
|
145
|
+
|
|
146
|
+
### Conditional Translation
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<Translate
|
|
150
|
+
text="Good morning!"
|
|
151
|
+
lang={userPreferredLanguage}
|
|
152
|
+
fallback="Loading translation..."
|
|
153
|
+
/>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Variable Interpolation
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
<Translate
|
|
160
|
+
text="You have {count} new messages"
|
|
161
|
+
ctx={{ count: unreadCount }}
|
|
162
|
+
/>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Manual Translation
|
|
166
|
+
|
|
167
|
+
```tsx
|
|
168
|
+
function ManualTranslation() {
|
|
169
|
+
const { engine } = useBelocal();
|
|
170
|
+
|
|
171
|
+
const handleTranslate = async () => {
|
|
172
|
+
try {
|
|
173
|
+
const result = await engine.t('Custom text', 'fr');
|
|
174
|
+
console.log(result);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error('Translation failed:', error);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
return <button onClick={handleTranslate}>Translate</button>;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
187
|
+
|
|
188
|
+
## Support
|
|
189
|
+
|
|
190
|
+
For issues and questions, please visit [GitHub Issues](https://github.com/belocal/sdk/issues).
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var jsSdk = require('@belocal/js-sdk');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/BelocalProvider.tsx
|
|
8
|
+
var BelocalContext = react.createContext(null);
|
|
9
|
+
var BelocalProvider = ({
|
|
10
|
+
apiKey,
|
|
11
|
+
baseUrl,
|
|
12
|
+
defaultLang,
|
|
13
|
+
children
|
|
14
|
+
}) => {
|
|
15
|
+
const contextValue = react.useMemo(() => {
|
|
16
|
+
const engine = new jsSdk.BelocalEngine({
|
|
17
|
+
apiKey,
|
|
18
|
+
baseUrl
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
engine,
|
|
22
|
+
defaultLang
|
|
23
|
+
};
|
|
24
|
+
}, [apiKey, baseUrl, defaultLang]);
|
|
25
|
+
return /* @__PURE__ */ jsxRuntime.jsx(BelocalContext.Provider, { value: contextValue, children });
|
|
26
|
+
};
|
|
27
|
+
var useBelocalContext = () => {
|
|
28
|
+
const context = react.useContext(BelocalContext);
|
|
29
|
+
if (!context) {
|
|
30
|
+
throw new Error("useBelocalContext must be used within a BelocalProvider");
|
|
31
|
+
}
|
|
32
|
+
return context;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/useBelocal.ts
|
|
36
|
+
var useBelocal = () => {
|
|
37
|
+
return useBelocalContext();
|
|
38
|
+
};
|
|
39
|
+
var Translate = ({
|
|
40
|
+
text,
|
|
41
|
+
lang,
|
|
42
|
+
ctx,
|
|
43
|
+
fallback
|
|
44
|
+
}) => {
|
|
45
|
+
const { engine, defaultLang } = useBelocal();
|
|
46
|
+
const [translatedText, setTranslatedText] = react.useState(fallback || text);
|
|
47
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
48
|
+
const targetLang = lang ?? defaultLang;
|
|
49
|
+
react.useEffect(() => {
|
|
50
|
+
if (!targetLang) {
|
|
51
|
+
setTranslatedText(text);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
setIsLoading(true);
|
|
55
|
+
engine.t(text, targetLang, ctx).then((translation) => {
|
|
56
|
+
setTranslatedText(translation);
|
|
57
|
+
}).catch((error) => {
|
|
58
|
+
console.error("Translation error:", error);
|
|
59
|
+
setTranslatedText(text);
|
|
60
|
+
}).finally(() => {
|
|
61
|
+
setIsLoading(false);
|
|
62
|
+
});
|
|
63
|
+
}, [text, targetLang, ctx, engine]);
|
|
64
|
+
if (isLoading) {
|
|
65
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback || text });
|
|
66
|
+
}
|
|
67
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: translatedText });
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
exports.BelocalProvider = BelocalProvider;
|
|
71
|
+
exports.Translate = Translate;
|
|
72
|
+
exports.useBelocal = useBelocal;
|
|
73
|
+
//# sourceMappingURL=index.cjs.map
|
|
74
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/BelocalProvider.tsx","../src/useBelocal.ts","../src/Translate.tsx"],"names":["createContext","useMemo","BelocalEngine","useContext","useState","useEffect","jsx","Fragment"],"mappings":";;;;;;;AAeA,IAAM,cAAA,GAAiBA,oBAAyC,IAAI,CAAA;AAE7D,IAAM,kBAAkD,CAAC;AAAA,EAC9D,MAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,YAAA,GAAeC,cAAQ,MAAM;AACjC,IAAA,MAAM,MAAA,GAAS,IAAIC,mBAAA,CAAc;AAAA,MAC/B,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,WAAW,CAAC,CAAA;AAEjC,EAAA,sCACG,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAO,cAC7B,QAAA,EACH,CAAA;AAEJ;AAEO,IAAM,oBAAoB,MAAM;AACrC,EAAA,MAAM,OAAA,GAAUC,iBAAW,cAAc,CAAA;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,OAAA;AACT,CAAA;;;AC9CO,IAAM,aAAa,MAAM;AAC9B,EAAA,OAAO,iBAAA,EAAkB;AAC3B;ACMO,IAAM,YAAsC,CAAC;AAAA,EAClD,IAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,UAAA,EAAW;AAC3C,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIC,cAAA,CAAiB,YAAY,IAAI,CAAA;AAC7E,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,eAAkB,KAAK,CAAA;AAGzD,EAAA,MAAM,aAAa,IAAA,IAAQ,WAAA;AAE3B,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,UAAA,EAAY;AAEf,MAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,YAAA,CAAa,IAAI,CAAA;AAEjB,IAAA,MAAA,CACG,EAAE,IAAA,EAAM,UAAA,EAAY,GAAG,CAAA,CACvB,IAAA,CAAK,CAAC,WAAA,KAAgB;AACrB,MAAA,iBAAA,CAAkB,WAAW,CAAA;AAAA,IAC/B,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AAEzC,MAAA,iBAAA,CAAkB,IAAI,CAAA;AAAA,IACxB,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB,CAAC,CAAA;AAAA,EACL,GAAG,CAAC,IAAA,EAAM,UAAA,EAAY,GAAA,EAAK,MAAM,CAAC,CAAA;AAGlC,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,uBAAOC,cAAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAA,QAAA,IAAY,IAAA,EAAK,CAAA;AAAA,EAC7B;AAEA,EAAA,uBAAOD,cAAAA,CAAAC,mBAAA,EAAA,EAAG,QAAA,EAAA,cAAA,EAAe,CAAA;AAC3B","file":"index.cjs","sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\nimport { BelocalEngine } from '@belocal/js-sdk';\n\nexport type BelocalProviderProps = {\n apiKey: string;\n baseUrl?: string;\n defaultLang?: string;\n children: React.ReactNode;\n};\n\ntype BelocalContextType = {\n engine: BelocalEngine;\n defaultLang?: string;\n};\n\nconst BelocalContext = createContext<BelocalContextType | null>(null);\n\nexport const BelocalProvider: React.FC<BelocalProviderProps> = ({\n apiKey,\n baseUrl,\n defaultLang,\n children,\n}) => {\n const contextValue = useMemo(() => {\n const engine = new BelocalEngine({\n apiKey,\n baseUrl,\n });\n\n return {\n engine,\n defaultLang,\n };\n }, [apiKey, baseUrl, defaultLang]);\n\n return (\n <BelocalContext.Provider value={contextValue}>\n {children}\n </BelocalContext.Provider>\n );\n};\n\nexport const useBelocalContext = () => {\n const context = useContext(BelocalContext);\n if (!context) {\n throw new Error('useBelocalContext must be used within a BelocalProvider');\n }\n return context;\n};\n\n","import { useBelocalContext } from './BelocalProvider';\n\nexport const useBelocal = () => {\n return useBelocalContext();\n};\n\n","import React, { useState, useEffect } from 'react';\nimport { useBelocal } from './useBelocal';\n\nexport type TranslateProps = {\n text: string;\n lang?: string;\n ctx?: Record<string, any>;\n fallback?: string;\n};\n\nexport const Translate: React.FC<TranslateProps> = ({\n text,\n lang,\n ctx,\n fallback,\n}) => {\n const { engine, defaultLang } = useBelocal();\n const [translatedText, setTranslatedText] = useState<string>(fallback || text);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n // Выбираем язык: props.lang имеет приоритет над defaultLang\n const targetLang = lang ?? defaultLang;\n\n useEffect(() => {\n if (!targetLang) {\n // Если язык не указан, просто возвращаем исходный текст\n setTranslatedText(text);\n return;\n }\n\n setIsLoading(true);\n \n engine\n .t(text, targetLang, ctx)\n .then((translation) => {\n setTranslatedText(translation);\n })\n .catch((error) => {\n console.error('Translation error:', error);\n // При ошибке возвращаем исходный текст\n setTranslatedText(text);\n })\n .finally(() => {\n setIsLoading(false);\n });\n }, [text, targetLang, ctx, engine]);\n\n // Пока идёт запрос — рендерим fallback или исходный text\n if (isLoading) {\n return <>{fallback || text}</>;\n }\n\n return <>{translatedText}</>;\n};\n\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as _belocal_js_sdk from '@belocal/js-sdk';
|
|
3
|
+
|
|
4
|
+
type BelocalProviderProps = {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
defaultLang?: string;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
declare const BelocalProvider: React.FC<BelocalProviderProps>;
|
|
11
|
+
|
|
12
|
+
declare const useBelocal: () => {
|
|
13
|
+
engine: _belocal_js_sdk.BelocalEngine;
|
|
14
|
+
defaultLang?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type TranslateProps = {
|
|
18
|
+
text: string;
|
|
19
|
+
lang?: string;
|
|
20
|
+
ctx?: Record<string, any>;
|
|
21
|
+
fallback?: string;
|
|
22
|
+
};
|
|
23
|
+
declare const Translate: React.FC<TranslateProps>;
|
|
24
|
+
|
|
25
|
+
export { BelocalProvider, type BelocalProviderProps, Translate, type TranslateProps, useBelocal };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import * as _belocal_js_sdk from '@belocal/js-sdk';
|
|
3
|
+
|
|
4
|
+
type BelocalProviderProps = {
|
|
5
|
+
apiKey: string;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
defaultLang?: string;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
declare const BelocalProvider: React.FC<BelocalProviderProps>;
|
|
11
|
+
|
|
12
|
+
declare const useBelocal: () => {
|
|
13
|
+
engine: _belocal_js_sdk.BelocalEngine;
|
|
14
|
+
defaultLang?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type TranslateProps = {
|
|
18
|
+
text: string;
|
|
19
|
+
lang?: string;
|
|
20
|
+
ctx?: Record<string, any>;
|
|
21
|
+
fallback?: string;
|
|
22
|
+
};
|
|
23
|
+
declare const Translate: React.FC<TranslateProps>;
|
|
24
|
+
|
|
25
|
+
export { BelocalProvider, type BelocalProviderProps, Translate, type TranslateProps, useBelocal };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createContext, useMemo, useState, useEffect, useContext } from 'react';
|
|
2
|
+
import { BelocalEngine } from '@belocal/js-sdk';
|
|
3
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/BelocalProvider.tsx
|
|
6
|
+
var BelocalContext = createContext(null);
|
|
7
|
+
var BelocalProvider = ({
|
|
8
|
+
apiKey,
|
|
9
|
+
baseUrl,
|
|
10
|
+
defaultLang,
|
|
11
|
+
children
|
|
12
|
+
}) => {
|
|
13
|
+
const contextValue = useMemo(() => {
|
|
14
|
+
const engine = new BelocalEngine({
|
|
15
|
+
apiKey,
|
|
16
|
+
baseUrl
|
|
17
|
+
});
|
|
18
|
+
return {
|
|
19
|
+
engine,
|
|
20
|
+
defaultLang
|
|
21
|
+
};
|
|
22
|
+
}, [apiKey, baseUrl, defaultLang]);
|
|
23
|
+
return /* @__PURE__ */ jsx(BelocalContext.Provider, { value: contextValue, children });
|
|
24
|
+
};
|
|
25
|
+
var useBelocalContext = () => {
|
|
26
|
+
const context = useContext(BelocalContext);
|
|
27
|
+
if (!context) {
|
|
28
|
+
throw new Error("useBelocalContext must be used within a BelocalProvider");
|
|
29
|
+
}
|
|
30
|
+
return context;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/useBelocal.ts
|
|
34
|
+
var useBelocal = () => {
|
|
35
|
+
return useBelocalContext();
|
|
36
|
+
};
|
|
37
|
+
var Translate = ({
|
|
38
|
+
text,
|
|
39
|
+
lang,
|
|
40
|
+
ctx,
|
|
41
|
+
fallback
|
|
42
|
+
}) => {
|
|
43
|
+
const { engine, defaultLang } = useBelocal();
|
|
44
|
+
const [translatedText, setTranslatedText] = useState(fallback || text);
|
|
45
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
46
|
+
const targetLang = lang ?? defaultLang;
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (!targetLang) {
|
|
49
|
+
setTranslatedText(text);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
setIsLoading(true);
|
|
53
|
+
engine.t(text, targetLang, ctx).then((translation) => {
|
|
54
|
+
setTranslatedText(translation);
|
|
55
|
+
}).catch((error) => {
|
|
56
|
+
console.error("Translation error:", error);
|
|
57
|
+
setTranslatedText(text);
|
|
58
|
+
}).finally(() => {
|
|
59
|
+
setIsLoading(false);
|
|
60
|
+
});
|
|
61
|
+
}, [text, targetLang, ctx, engine]);
|
|
62
|
+
if (isLoading) {
|
|
63
|
+
return /* @__PURE__ */ jsx(Fragment, { children: fallback || text });
|
|
64
|
+
}
|
|
65
|
+
return /* @__PURE__ */ jsx(Fragment, { children: translatedText });
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { BelocalProvider, Translate, useBelocal };
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
70
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/BelocalProvider.tsx","../src/useBelocal.ts","../src/Translate.tsx"],"names":["jsx"],"mappings":";;;;;AAeA,IAAM,cAAA,GAAiB,cAAyC,IAAI,CAAA;AAE7D,IAAM,kBAAkD,CAAC;AAAA,EAC9D,MAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,YAAA,GAAe,QAAQ,MAAM;AACjC,IAAA,MAAM,MAAA,GAAS,IAAI,aAAA,CAAc;AAAA,MAC/B,MAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA,EAAG,CAAC,MAAA,EAAQ,OAAA,EAAS,WAAW,CAAC,CAAA;AAEjC,EAAA,2BACG,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAO,cAC7B,QAAA,EACH,CAAA;AAEJ;AAEO,IAAM,oBAAoB,MAAM;AACrC,EAAA,MAAM,OAAA,GAAU,WAAW,cAAc,CAAA;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,OAAA;AACT,CAAA;;;AC9CO,IAAM,aAAa,MAAM;AAC9B,EAAA,OAAO,iBAAA,EAAkB;AAC3B;ACMO,IAAM,YAAsC,CAAC;AAAA,EAClD,IAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAY,GAAI,UAAA,EAAW;AAC3C,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAI,QAAA,CAAiB,YAAY,IAAI,CAAA;AAC7E,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAkB,KAAK,CAAA;AAGzD,EAAA,MAAM,aAAa,IAAA,IAAQ,WAAA;AAE3B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,UAAA,EAAY;AAEf,MAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,YAAA,CAAa,IAAI,CAAA;AAEjB,IAAA,MAAA,CACG,EAAE,IAAA,EAAM,UAAA,EAAY,GAAG,CAAA,CACvB,IAAA,CAAK,CAAC,WAAA,KAAgB;AACrB,MAAA,iBAAA,CAAkB,WAAW,CAAA;AAAA,IAC/B,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,MAAA,OAAA,CAAQ,KAAA,CAAM,sBAAsB,KAAK,CAAA;AAEzC,MAAA,iBAAA,CAAkB,IAAI,CAAA;AAAA,IACxB,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB,CAAC,CAAA;AAAA,EACL,GAAG,CAAC,IAAA,EAAM,UAAA,EAAY,GAAA,EAAK,MAAM,CAAC,CAAA;AAGlC,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,uBAAOA,GAAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,QAAA,IAAY,IAAA,EAAK,CAAA;AAAA,EAC7B;AAEA,EAAA,uBAAOA,GAAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAA,cAAA,EAAe,CAAA;AAC3B","file":"index.js","sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\nimport { BelocalEngine } from '@belocal/js-sdk';\n\nexport type BelocalProviderProps = {\n apiKey: string;\n baseUrl?: string;\n defaultLang?: string;\n children: React.ReactNode;\n};\n\ntype BelocalContextType = {\n engine: BelocalEngine;\n defaultLang?: string;\n};\n\nconst BelocalContext = createContext<BelocalContextType | null>(null);\n\nexport const BelocalProvider: React.FC<BelocalProviderProps> = ({\n apiKey,\n baseUrl,\n defaultLang,\n children,\n}) => {\n const contextValue = useMemo(() => {\n const engine = new BelocalEngine({\n apiKey,\n baseUrl,\n });\n\n return {\n engine,\n defaultLang,\n };\n }, [apiKey, baseUrl, defaultLang]);\n\n return (\n <BelocalContext.Provider value={contextValue}>\n {children}\n </BelocalContext.Provider>\n );\n};\n\nexport const useBelocalContext = () => {\n const context = useContext(BelocalContext);\n if (!context) {\n throw new Error('useBelocalContext must be used within a BelocalProvider');\n }\n return context;\n};\n\n","import { useBelocalContext } from './BelocalProvider';\n\nexport const useBelocal = () => {\n return useBelocalContext();\n};\n\n","import React, { useState, useEffect } from 'react';\nimport { useBelocal } from './useBelocal';\n\nexport type TranslateProps = {\n text: string;\n lang?: string;\n ctx?: Record<string, any>;\n fallback?: string;\n};\n\nexport const Translate: React.FC<TranslateProps> = ({\n text,\n lang,\n ctx,\n fallback,\n}) => {\n const { engine, defaultLang } = useBelocal();\n const [translatedText, setTranslatedText] = useState<string>(fallback || text);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n\n // Выбираем язык: props.lang имеет приоритет над defaultLang\n const targetLang = lang ?? defaultLang;\n\n useEffect(() => {\n if (!targetLang) {\n // Если язык не указан, просто возвращаем исходный текст\n setTranslatedText(text);\n return;\n }\n\n setIsLoading(true);\n \n engine\n .t(text, targetLang, ctx)\n .then((translation) => {\n setTranslatedText(translation);\n })\n .catch((error) => {\n console.error('Translation error:', error);\n // При ошибке возвращаем исходный текст\n setTranslatedText(text);\n })\n .finally(() => {\n setIsLoading(false);\n });\n }, [text, targetLang, ctx, engine]);\n\n // Пока идёт запрос — рендерим fallback или исходный text\n if (isLoading) {\n return <>{fallback || text}</>;\n }\n\n return <>{translatedText}</>;\n};\n\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@belocal/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React SDK for Belocal translation service",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "bobredobre <bobredobre@belocal.dev>",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.cjs",
|
|
9
|
+
"module": "dist/index.mjs",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.mjs"
|
|
16
|
+
},
|
|
17
|
+
"require": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.cjs"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"dev": "tsup --watch",
|
|
31
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": ">=17.0.0",
|
|
35
|
+
"react-dom": ">=17.0.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@belocal/js-sdk": "^0.1.12"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/react": "^18.0.0",
|
|
42
|
+
"@types/react-dom": "^18.0.0",
|
|
43
|
+
"react": "^18.0.0",
|
|
44
|
+
"react-dom": "^18.0.0",
|
|
45
|
+
"typescript": "^5.0.0",
|
|
46
|
+
"tsup": "^8.0.0"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
}
|
|
51
|
+
}
|