@proveanything/smartlinks 1.2.4 → 1.3.2
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 +85 -1
- package/{API_SUMMARY.md → dist/API_SUMMARY.md} +225 -1
- package/dist/README.md +569 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +2 -0
- package/dist/api/realtime.d.ts +103 -0
- package/dist/api/realtime.js +113 -0
- package/dist/docs/API_SUMMARY.md +3230 -0
- package/dist/docs/i18n.md +287 -0
- package/dist/docs/liquid-templates.md +484 -0
- package/dist/docs/realtime.md +764 -0
- package/dist/docs/theme-defaults.md +100 -0
- package/dist/docs/theme.system.md +338 -0
- package/dist/docs/widgets.md +510 -0
- package/dist/http.js +132 -19
- package/dist/i18n.md +287 -0
- package/dist/liquid-templates.md +484 -0
- package/dist/realtime.md +764 -0
- package/dist/theme-defaults.md +100 -0
- package/dist/theme.system.md +338 -0
- package/dist/types/error.d.ts +69 -3
- package/dist/types/error.js +98 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/realtime.d.ts +44 -0
- package/dist/types/realtime.js +2 -0
- package/dist/widgets.md +510 -0
- package/docs/API_SUMMARY.md +3230 -0
- package/docs/i18n.md +287 -0
- package/docs/liquid-templates.md +484 -0
- package/docs/realtime.md +764 -0
- package/docs/theme-defaults.md +100 -0
- package/docs/theme.system.md +338 -0
- package/docs/widgets.md +510 -0
- package/package.json +4 -4
- package/dist/api/actions.d.ts +0 -32
- package/dist/api/actions.js +0 -99
- package/dist/build-docs.js +0 -61
- package/dist/types/actions.d.ts +0 -123
- package/dist/types/actions.js +0 -2
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Internationalization (i18n) System
|
|
2
|
+
|
|
3
|
+
This document explains the i18n system for SmartLinks apps, covering URL-based language selection, static translations, and dynamic overrides.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
The i18n system supports:
|
|
10
|
+
|
|
11
|
+
- **URL parameter language selection** (`?lang=de`) - Ideal for iframe embedding
|
|
12
|
+
- **Static translations** in JSON files - Fast, no API calls
|
|
13
|
+
- **Dynamic overrides** via SmartLinks appConfig - Customer-configurable
|
|
14
|
+
- **Type-safe translation keys** - Compile-time safety
|
|
15
|
+
- **Widget support** - Translations can be passed to embedded widgets
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### Using Translations in Components
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { useLanguage } from '@/i18n';
|
|
25
|
+
|
|
26
|
+
export const MyComponent = () => {
|
|
27
|
+
const { t, lang } = useLanguage();
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div>
|
|
31
|
+
<h1>{t('public.title')}</h1>
|
|
32
|
+
<p>{t('public.description')}</p>
|
|
33
|
+
<small>Language: {lang}</small>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### With Parameter Interpolation
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
const { t } = useLanguage();
|
|
43
|
+
|
|
44
|
+
// Translation: "Hello, {{name}}!"
|
|
45
|
+
t('greeting', { name: 'John' }); // "Hello, John!"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Language Detection Priority
|
|
51
|
+
|
|
52
|
+
The system detects language from multiple sources (in order):
|
|
53
|
+
|
|
54
|
+
| Priority | Source | Example |
|
|
55
|
+
|----------|--------|---------|
|
|
56
|
+
| 1 | URL parameter | `?lang=de` |
|
|
57
|
+
| 2 | localStorage | `smartlinks-lang` key |
|
|
58
|
+
| 3 | Browser language | `navigator.language` |
|
|
59
|
+
| 4 | Default | `en` |
|
|
60
|
+
|
|
61
|
+
For iframe apps, the SmartLinks platform passes the language via URL parameter.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## File Structure
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
src/i18n/
|
|
69
|
+
├── index.ts # Main exports
|
|
70
|
+
├── LanguageContext.tsx # React context + provider
|
|
71
|
+
├── types.ts # TypeScript types
|
|
72
|
+
└── locales/
|
|
73
|
+
├── en.json # English translations
|
|
74
|
+
├── de.json # German translations
|
|
75
|
+
└── fr.json # French translations
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Adding New Translations
|
|
81
|
+
|
|
82
|
+
### 1. Add the Key to Types
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// src/i18n/types.ts
|
|
86
|
+
export type TranslationKey =
|
|
87
|
+
| 'common.loading'
|
|
88
|
+
| 'common.error'
|
|
89
|
+
| 'myFeature.title' // Add new key
|
|
90
|
+
| 'myFeature.description';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 2. Add Translations to All Locales
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
// src/i18n/locales/en.json
|
|
97
|
+
{
|
|
98
|
+
"myFeature.title": "My Feature",
|
|
99
|
+
"myFeature.description": "Description of my feature"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/i18n/locales/de.json
|
|
103
|
+
{
|
|
104
|
+
"myFeature.title": "Meine Funktion",
|
|
105
|
+
"myFeature.description": "Beschreibung meiner Funktion"
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 3. Use in Components
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const { t } = useLanguage();
|
|
113
|
+
return <h1>{t('myFeature.title')}</h1>;
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Adding New Languages
|
|
119
|
+
|
|
120
|
+
### 1. Create the Locale File
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
// src/i18n/locales/es.json
|
|
124
|
+
{
|
|
125
|
+
"common.loading": "Cargando...",
|
|
126
|
+
"common.error": "Algo salió mal",
|
|
127
|
+
// ... all other keys
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 2. Import in LanguageContext
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// src/i18n/LanguageContext.tsx
|
|
135
|
+
import es from './locales/es.json';
|
|
136
|
+
|
|
137
|
+
const staticTranslations: Record<string, PartialTranslations> = {
|
|
138
|
+
en: en as PartialTranslations,
|
|
139
|
+
de: de as PartialTranslations,
|
|
140
|
+
fr: fr as PartialTranslations,
|
|
141
|
+
es: es as PartialTranslations, // Add new language
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const SUPPORTED_LANGUAGES = ['en', 'de', 'fr', 'es']; // Add to list
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Dynamic Translations (SmartLinks appConfig)
|
|
150
|
+
|
|
151
|
+
For customer-configurable translations, store them in SmartLinks appConfig:
|
|
152
|
+
|
|
153
|
+
### Config Structure
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"i18n": {
|
|
158
|
+
"supportedLanguages": ["en", "de"],
|
|
159
|
+
"defaultLanguage": "en",
|
|
160
|
+
"translations": {
|
|
161
|
+
"en": {
|
|
162
|
+
"public.title": "Custom Brand Title",
|
|
163
|
+
"public.description": "Custom brand description"
|
|
164
|
+
},
|
|
165
|
+
"de": {
|
|
166
|
+
"public.title": "Benutzerdefinierter Markentitel",
|
|
167
|
+
"public.description": "Benutzerdefinierte Markenbeschreibung"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Loading Dynamic Translations
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { useCollectionAppConfig } from '@/hooks/useSmartLinksData';
|
|
178
|
+
import { LanguageProvider } from '@/i18n';
|
|
179
|
+
|
|
180
|
+
const App = () => {
|
|
181
|
+
const { data: config } = useCollectionAppConfig(collectionId, appId);
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<LanguageProvider dynamicTranslations={config?.i18n?.translations}>
|
|
185
|
+
<MyApp />
|
|
186
|
+
</LanguageProvider>
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Dynamic translations override static ones, so customers can customize specific strings while inheriting defaults.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Widgets
|
|
196
|
+
|
|
197
|
+
Widgets receive language context via props rather than React context (since they may run outside the provider).
|
|
198
|
+
|
|
199
|
+
### Widget Props
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
interface SmartLinksWidgetProps {
|
|
203
|
+
// ... other props
|
|
204
|
+
lang?: string;
|
|
205
|
+
translations?: Record<string, string>;
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Using in Widgets
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
import { createTranslator } from '@/i18n';
|
|
213
|
+
|
|
214
|
+
export const MyWidget: React.FC<SmartLinksWidgetProps> = ({
|
|
215
|
+
lang = 'en',
|
|
216
|
+
translations = {},
|
|
217
|
+
...props
|
|
218
|
+
}) => {
|
|
219
|
+
const t = createTranslator(lang, translations);
|
|
220
|
+
|
|
221
|
+
return <div>{t('widget.title')}</div>;
|
|
222
|
+
};
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The `createTranslator` function creates a standalone translation function that doesn't require React context.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## URL Examples
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
# English (default)
|
|
233
|
+
/#/?collectionId=abc&appId=pamphlet
|
|
234
|
+
|
|
235
|
+
# German
|
|
236
|
+
/#/?collectionId=abc&appId=pamphlet&lang=de
|
|
237
|
+
|
|
238
|
+
# French
|
|
239
|
+
/#/?collectionId=abc&appId=pamphlet&lang=fr
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Best Practices
|
|
245
|
+
|
|
246
|
+
1. **Use dot notation** for key namespacing: `category.subcategory.key`
|
|
247
|
+
2. **Keep translations flat** - avoid nested objects in locale files
|
|
248
|
+
3. **Add keys to types.ts first** - ensures type safety
|
|
249
|
+
4. **Provide fallbacks** - English is always the fallback language
|
|
250
|
+
5. **Test all languages** - Use `?lang=xx` to switch during development
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## API Reference
|
|
255
|
+
|
|
256
|
+
### `useLanguage()`
|
|
257
|
+
|
|
258
|
+
Hook to access language context.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
const {
|
|
262
|
+
lang, // Current language code
|
|
263
|
+
setLang, // Function to change language
|
|
264
|
+
t, // Translation function
|
|
265
|
+
supportedLanguages // Array of supported language codes
|
|
266
|
+
} = useLanguage();
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### `createTranslator(lang, overrides)`
|
|
270
|
+
|
|
271
|
+
Creates a standalone translation function for widgets.
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
const t = createTranslator('de', { 'custom.key': 'Custom value' });
|
|
275
|
+
t('common.loading'); // "Laden..."
|
|
276
|
+
t('custom.key'); // "Custom value"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### `LanguageProvider`
|
|
280
|
+
|
|
281
|
+
React provider component.
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
<LanguageProvider dynamicTranslations={optionalOverrides}>
|
|
285
|
+
<App />
|
|
286
|
+
</LanguageProvider>
|
|
287
|
+
```
|