@idealyst/mcp-server 1.2.7 → 1.2.8

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.
@@ -0,0 +1,1030 @@
1
+ export const translateGuides = {
2
+ "idealyst://translate/overview": `# @idealyst/translate Overview
3
+
4
+ Cross-platform internationalization for the Idealyst Framework. Wraps \`react-i18next\` with a unified API and includes a Babel plugin for static translation key analysis.
5
+
6
+ ## Core Features
7
+
8
+ - **Unified API** - Single API for React and React Native
9
+ - **Babel Plugin** - Static extraction of translation keys at build time
10
+ - **Missing Translation Detection** - Automatically detect keys missing translations
11
+ - **Unused Translation Detection** - Find translations not used in code
12
+ - **JSON Report** - Generate detailed reports for CI/CD integration
13
+ - **Namespace Support** - Organize translations with nested namespaces
14
+ - **Pluralization** - Full i18next pluralization support
15
+ - **Interpolation** - Variable interpolation in translations
16
+ - **Rich Text** - Component interpolation with the Trans component
17
+
18
+ ## Installation
19
+
20
+ \`\`\`bash
21
+ yarn add @idealyst/translate react-i18next i18next
22
+ \`\`\`
23
+
24
+ ## Quick Start
25
+
26
+ ### 1. Create Translation Files
27
+
28
+ \`\`\`
29
+ locales/
30
+ ├── en/
31
+ │ └── common.json
32
+ └── es/
33
+ └── common.json
34
+ \`\`\`
35
+
36
+ **locales/en/common.json**
37
+ \`\`\`json
38
+ {
39
+ "welcome": {
40
+ "title": "Welcome to Our App",
41
+ "greeting": "Hello, {{name}}!"
42
+ },
43
+ "buttons": {
44
+ "submit": "Submit",
45
+ "cancel": "Cancel"
46
+ }
47
+ }
48
+ \`\`\`
49
+
50
+ ### 2. Set Up the Provider
51
+
52
+ \`\`\`tsx
53
+ import { TranslateProvider } from '@idealyst/translate';
54
+ import en from './locales/en/common.json';
55
+ import es from './locales/es/common.json';
56
+
57
+ const config = {
58
+ defaultLanguage: 'en',
59
+ languages: ['en', 'es'],
60
+ resources: {
61
+ en: { common: en },
62
+ es: { common: es },
63
+ },
64
+ defaultNamespace: 'common',
65
+ };
66
+
67
+ export function App() {
68
+ return (
69
+ <TranslateProvider config={config}>
70
+ <MyApp />
71
+ </TranslateProvider>
72
+ );
73
+ }
74
+ \`\`\`
75
+
76
+ ### 3. Use Translations
77
+
78
+ \`\`\`tsx
79
+ import { useTranslation } from '@idealyst/translate';
80
+
81
+ function MyComponent() {
82
+ const { t } = useTranslation('common');
83
+
84
+ return (
85
+ <div>
86
+ <h1>{t('welcome.title')}</h1>
87
+ <p>{t('welcome.greeting', { name: 'John' })}</p>
88
+ <button>{t('buttons.submit')}</button>
89
+ </div>
90
+ );
91
+ }
92
+ \`\`\`
93
+
94
+ ## Key Concepts
95
+
96
+ ### Key Formats
97
+ The package supports two key formats:
98
+
99
+ \`\`\`tsx
100
+ // Namespace:key format (i18next standard)
101
+ t('auth:login.title')
102
+
103
+ // Namespace.key format (first segment is namespace)
104
+ t('auth.login.title')
105
+ \`\`\`
106
+
107
+ ### Namespace Organization
108
+ Organize translations by domain:
109
+ - \`common.json\` - Shared UI strings
110
+ - \`auth.json\` - Authentication strings
111
+ - \`errors.json\` - Error messages
112
+ - \`forms.json\` - Form labels and validation
113
+ `,
114
+ "idealyst://translate/runtime-api": `# Runtime API Reference
115
+
116
+ Complete reference for the @idealyst/translate runtime API.
117
+
118
+ ## TranslateProvider
119
+
120
+ Wrap your app with the provider to enable translations:
121
+
122
+ \`\`\`tsx
123
+ import { TranslateProvider } from '@idealyst/translate';
124
+
125
+ <TranslateProvider
126
+ config={{
127
+ defaultLanguage: 'en',
128
+ languages: ['en', 'es', 'fr'],
129
+ resources: {
130
+ en: { common: enCommon, auth: enAuth },
131
+ es: { common: esCommon, auth: esAuth },
132
+ },
133
+ defaultNamespace: 'common',
134
+ fallbackLanguage: 'en',
135
+ debug: false,
136
+ }}
137
+ onInitialized={(i18n) => console.log('i18n ready')}
138
+ onLanguageChanged={(lang) => console.log('Language:', lang)}
139
+ >
140
+ <App />
141
+ </TranslateProvider>
142
+ \`\`\`
143
+
144
+ ### TranslateConfig Options
145
+
146
+ | Option | Type | Required | Description |
147
+ |--------|------|----------|-------------|
148
+ | \`defaultLanguage\` | string | Yes | Default language code |
149
+ | \`languages\` | string[] | Yes | Supported language codes |
150
+ | \`resources\` | object | No | Pre-loaded translation resources |
151
+ | \`defaultNamespace\` | string | No | Default namespace (default: 'translation') |
152
+ | \`fallbackLanguage\` | string | No | Fallback when key missing |
153
+ | \`debug\` | boolean | No | Enable debug logging |
154
+
155
+ ## useTranslation Hook
156
+
157
+ The main hook for accessing translations:
158
+
159
+ \`\`\`tsx
160
+ import { useTranslation } from '@idealyst/translate';
161
+
162
+ function Component() {
163
+ const { t, language, languages, ready, i18n } = useTranslation('common');
164
+
165
+ // Simple translation
166
+ const title = t('welcome.title');
167
+
168
+ // With interpolation
169
+ const greeting = t('welcome.greeting', { name: 'World' });
170
+
171
+ // With default value
172
+ const fallback = t('missing.key', { defaultValue: 'Fallback text' });
173
+
174
+ // With pluralization
175
+ const items = t('items', { count: 5 });
176
+
177
+ // With context
178
+ const gendered = t('liked', { context: 'male' });
179
+
180
+ return <div>{title}</div>;
181
+ }
182
+ \`\`\`
183
+
184
+ ### Return Values
185
+
186
+ | Property | Type | Description |
187
+ |----------|------|-------------|
188
+ | \`t\` | function | Translation function |
189
+ | \`language\` | string | Current language code |
190
+ | \`languages\` | string[] | All available languages |
191
+ | \`ready\` | boolean | Whether translations are loaded |
192
+ | \`i18n\` | i18n | i18next instance for advanced usage |
193
+
194
+ ### Translation Options
195
+
196
+ \`\`\`tsx
197
+ t('key', {
198
+ // Default value if key not found
199
+ defaultValue: 'Fallback',
200
+
201
+ // Interpolation values
202
+ name: 'John',
203
+ count: 5,
204
+
205
+ // Pluralization count
206
+ count: 3,
207
+
208
+ // Context for contextual translations
209
+ context: 'male',
210
+ });
211
+ \`\`\`
212
+
213
+ ## useLanguage Hook
214
+
215
+ For language management:
216
+
217
+ \`\`\`tsx
218
+ import { useLanguage } from '@idealyst/translate';
219
+
220
+ function LanguageControls() {
221
+ const {
222
+ language, // Current: 'en'
223
+ languages, // Available: ['en', 'es', 'fr']
224
+ setLanguage, // Change language
225
+ isSupported, // Check availability
226
+ getDisplayName, // Get 'English', 'Español'
227
+ } = useLanguage();
228
+
229
+ return (
230
+ <select value={language} onChange={(e) => setLanguage(e.target.value)}>
231
+ {languages.map((lang) => (
232
+ <option key={lang} value={lang}>
233
+ {getDisplayName(lang)}
234
+ </option>
235
+ ))}
236
+ </select>
237
+ );
238
+ }
239
+ \`\`\`
240
+
241
+ ## Trans Component
242
+
243
+ For rich text with embedded components:
244
+
245
+ \`\`\`tsx
246
+ import { Trans } from '@idealyst/translate';
247
+
248
+ function RichText() {
249
+ return (
250
+ <Trans
251
+ i18nKey="common.richText"
252
+ components={{
253
+ terms: <a href="/terms" />,
254
+ privacy: <a href="/privacy" />,
255
+ bold: <strong />,
256
+ }}
257
+ values={{ name: 'User' }}
258
+ />
259
+ );
260
+ }
261
+
262
+ // Translation:
263
+ // "richText": "Read our <terms>Terms</terms> and <privacy>Privacy Policy</privacy>"
264
+ //
265
+ // Renders:
266
+ // Read our <a href="/terms">Terms</a> and <a href="/privacy">Privacy Policy</a>
267
+ \`\`\`
268
+
269
+ ### Trans Props
270
+
271
+ | Prop | Type | Required | Description |
272
+ |------|------|----------|-------------|
273
+ | \`i18nKey\` | string | Yes | Translation key |
274
+ | \`ns\` | string | No | Namespace |
275
+ | \`components\` | object | No | Component interpolations |
276
+ | \`values\` | object | No | Value interpolations |
277
+ | \`count\` | number | No | Pluralization count |
278
+ `,
279
+ "idealyst://translate/babel-plugin": `# Babel Plugin Reference
280
+
281
+ The Babel plugin extracts translation keys at build time and generates reports of missing/unused translations.
282
+
283
+ ## Installation
284
+
285
+ The plugin is included with @idealyst/translate. Just configure it in your Babel config.
286
+
287
+ ## Configuration
288
+
289
+ ### babel.config.js
290
+
291
+ \`\`\`javascript
292
+ module.exports = {
293
+ presets: ['@babel/preset-react', '@babel/preset-typescript'],
294
+ plugins: [
295
+ ['@idealyst/translate/plugin', {
296
+ // Required: paths to translation JSON files
297
+ translationFiles: ['./locales/**/*.json'],
298
+
299
+ // Optional: output path for the report
300
+ reportPath: '.idealyst/translations-report.json',
301
+
302
+ // Optional: default namespace
303
+ defaultNamespace: 'common',
304
+
305
+ // Optional: emit console warnings
306
+ emitWarnings: true,
307
+
308
+ // Optional: fail build on missing translations
309
+ failOnMissing: false,
310
+
311
+ // Optional: verbose logging
312
+ verbose: false,
313
+ }],
314
+ ],
315
+ };
316
+ \`\`\`
317
+
318
+ ### Vite Configuration
319
+
320
+ \`\`\`typescript
321
+ // vite.config.ts
322
+ import { defineConfig } from 'vite';
323
+ import react from '@vitejs/plugin-react';
324
+
325
+ export default defineConfig({
326
+ plugins: [
327
+ react({
328
+ babel: {
329
+ plugins: [
330
+ ['@idealyst/translate/plugin', {
331
+ translationFiles: ['./locales/**/*.json'],
332
+ reportPath: '.idealyst/translations-report.json',
333
+ defaultNamespace: 'common',
334
+ }],
335
+ ],
336
+ },
337
+ }),
338
+ ],
339
+ });
340
+ \`\`\`
341
+
342
+ ### React Native Configuration
343
+
344
+ \`\`\`javascript
345
+ // babel.config.js
346
+ module.exports = {
347
+ presets: ['module:@react-native/babel-preset'],
348
+ plugins: [
349
+ ['@idealyst/translate/plugin', {
350
+ translationFiles: ['./locales/**/*.json'],
351
+ reportPath: '.idealyst/translations-report.json',
352
+ defaultNamespace: 'common',
353
+ emitWarnings: true,
354
+ }],
355
+ ],
356
+ };
357
+ \`\`\`
358
+
359
+ ## Plugin Options
360
+
361
+ | Option | Type | Default | Description |
362
+ |--------|------|---------|-------------|
363
+ | \`translationFiles\` | string[] | Required | Glob patterns for translation files |
364
+ | \`reportPath\` | string | '.idealyst/translations-report.json' | Output path for report |
365
+ | \`languages\` | string[] | Auto-detected | Languages to check |
366
+ | \`defaultNamespace\` | string | 'translation' | Default namespace |
367
+ | \`failOnMissing\` | boolean | false | Fail build if missing |
368
+ | \`emitWarnings\` | boolean | true | Console warnings |
369
+ | \`verbose\` | boolean | false | Verbose logging |
370
+
371
+ ## What Gets Extracted
372
+
373
+ The plugin statically analyzes your code for:
374
+
375
+ \`\`\`tsx
376
+ // t() function calls
377
+ t('common.key')
378
+ t('namespace:key')
379
+ t('key', { defaultValue: 'Default' })
380
+
381
+ // i18n.t() method calls
382
+ i18n.t('common.key')
383
+
384
+ // Trans component
385
+ <Trans i18nKey="common.richText" />
386
+ <Trans i18nKey={"common.richText"} />
387
+
388
+ // Dynamic keys (tracked but marked as dynamic)
389
+ const key = \`common.\${type}\`;
390
+ t(key); // Marked as isDynamic: true
391
+ \`\`\`
392
+
393
+ ## Report Structure
394
+
395
+ The plugin generates a JSON report:
396
+
397
+ \`\`\`json
398
+ {
399
+ "timestamp": "2026-01-08T12:00:00.000Z",
400
+ "totalKeys": 45,
401
+ "dynamicKeys": [
402
+ {
403
+ "key": "<dynamic>",
404
+ "file": "src/DynamicComponent.tsx",
405
+ "line": 15,
406
+ "isDynamic": true
407
+ }
408
+ ],
409
+ "extractedKeys": [
410
+ {
411
+ "key": "common.buttons.submit",
412
+ "namespace": "common",
413
+ "localKey": "buttons.submit",
414
+ "file": "src/Form.tsx",
415
+ "line": 42,
416
+ "column": 12,
417
+ "defaultValue": "Submit",
418
+ "isDynamic": false
419
+ }
420
+ ],
421
+ "languages": ["en", "es", "fr"],
422
+ "missing": {
423
+ "en": [],
424
+ "es": [
425
+ {
426
+ "key": "common.buttons.submit",
427
+ "namespace": "common",
428
+ "usedIn": [
429
+ { "file": "src/Form.tsx", "line": 42, "column": 12 }
430
+ ],
431
+ "defaultValue": "Submit"
432
+ }
433
+ ]
434
+ },
435
+ "unused": {
436
+ "en": ["common.legacy.oldFeature"]
437
+ },
438
+ "summary": {
439
+ "totalMissing": 1,
440
+ "totalUnused": 1,
441
+ "coveragePercent": {
442
+ "en": 100,
443
+ "es": 98,
444
+ "fr": 100
445
+ }
446
+ }
447
+ }
448
+ \`\`\`
449
+
450
+ ## CI/CD Integration
451
+
452
+ ### GitHub Actions
453
+
454
+ \`\`\`yaml
455
+ name: Translation Check
456
+
457
+ on: [push, pull_request]
458
+
459
+ jobs:
460
+ check-translations:
461
+ runs-on: ubuntu-latest
462
+ steps:
463
+ - uses: actions/checkout@v3
464
+ - uses: actions/setup-node@v3
465
+ with:
466
+ node-version: '20'
467
+ - run: yarn install
468
+ - run: yarn build
469
+ - name: Check missing translations
470
+ run: |
471
+ MISSING=$(jq '.summary.totalMissing' .idealyst/translations-report.json)
472
+ if [ "$MISSING" -gt 0 ]; then
473
+ echo "Missing translations: $MISSING"
474
+ jq '.missing' .idealyst/translations-report.json
475
+ exit 1
476
+ fi
477
+ \`\`\`
478
+
479
+ ### Shell Script
480
+
481
+ \`\`\`bash
482
+ #!/bin/bash
483
+ yarn build
484
+
485
+ MISSING=$(jq '.summary.totalMissing' .idealyst/translations-report.json)
486
+
487
+ if [ "$MISSING" -gt 0 ]; then
488
+ echo "ERROR: $MISSING missing translation(s)"
489
+ jq -r '.missing | to_entries[] | select(.value | length > 0) | "\\(.key): \\(.value | length) missing"' \\
490
+ .idealyst/translations-report.json
491
+ exit 1
492
+ fi
493
+
494
+ echo "All translations present!"
495
+ \`\`\`
496
+ `,
497
+ "idealyst://translate/translation-files": `# Translation File Format
498
+
499
+ Guide to organizing and formatting translation files for @idealyst/translate.
500
+
501
+ ## Directory Structure
502
+
503
+ Organize translations by language and namespace:
504
+
505
+ \`\`\`
506
+ locales/
507
+ ├── en/
508
+ │ ├── common.json # Common UI strings
509
+ │ ├── auth.json # Authentication strings
510
+ │ ├── errors.json # Error messages
511
+ │ └── forms.json # Form labels
512
+ ├── es/
513
+ │ ├── common.json
514
+ │ ├── auth.json
515
+ │ ├── errors.json
516
+ │ └── forms.json
517
+ └── fr/
518
+ ├── common.json
519
+ ├── auth.json
520
+ ├── errors.json
521
+ └── forms.json
522
+ \`\`\`
523
+
524
+ ## JSON Format
525
+
526
+ ### Basic Structure
527
+
528
+ \`\`\`json
529
+ {
530
+ "simple": "Simple text",
531
+
532
+ "nested": {
533
+ "keys": {
534
+ "work": "Like this"
535
+ }
536
+ }
537
+ }
538
+ \`\`\`
539
+
540
+ ### Interpolation
541
+
542
+ Use \`{{variable}}\` for dynamic values:
543
+
544
+ \`\`\`json
545
+ {
546
+ "greeting": "Hello, {{name}}!",
547
+ "welcome": "Welcome back, {{user}}. You have {{count}} messages."
548
+ }
549
+ \`\`\`
550
+
551
+ Usage:
552
+ \`\`\`tsx
553
+ t('greeting', { name: 'John' }) // "Hello, John!"
554
+ t('welcome', { user: 'Alice', count: 5 }) // "Welcome back, Alice. You have 5 messages."
555
+ \`\`\`
556
+
557
+ ### Pluralization
558
+
559
+ Add \`_plural\` suffix for plural forms:
560
+
561
+ \`\`\`json
562
+ {
563
+ "item": "{{count}} item",
564
+ "item_plural": "{{count}} items",
565
+
566
+ "message": "You have {{count}} new message",
567
+ "message_plural": "You have {{count}} new messages"
568
+ }
569
+ \`\`\`
570
+
571
+ Usage:
572
+ \`\`\`tsx
573
+ t('item', { count: 1 }) // "1 item"
574
+ t('item', { count: 5 }) // "5 items"
575
+ \`\`\`
576
+
577
+ ### Context
578
+
579
+ Add \`_context\` suffix for contextual variations:
580
+
581
+ \`\`\`json
582
+ {
583
+ "friend": "A friend",
584
+ "friend_male": "A boyfriend",
585
+ "friend_female": "A girlfriend"
586
+ }
587
+ \`\`\`
588
+
589
+ Usage:
590
+ \`\`\`tsx
591
+ t('friend') // "A friend"
592
+ t('friend', { context: 'male' }) // "A boyfriend"
593
+ t('friend', { context: 'female' }) // "A girlfriend"
594
+ \`\`\`
595
+
596
+ ### Rich Text (Trans Component)
597
+
598
+ Use HTML-like tags for component interpolation:
599
+
600
+ \`\`\`json
601
+ {
602
+ "terms": "By signing up, you agree to our <terms>Terms of Service</terms> and <privacy>Privacy Policy</privacy>.",
603
+ "welcome": "Welcome, <bold>{{name}}</bold>! Click <link>here</link> to continue."
604
+ }
605
+ \`\`\`
606
+
607
+ Usage:
608
+ \`\`\`tsx
609
+ <Trans
610
+ i18nKey="common.terms"
611
+ components={{
612
+ terms: <a href="/terms" />,
613
+ privacy: <a href="/privacy" />,
614
+ }}
615
+ />
616
+ \`\`\`
617
+
618
+ ## Namespace Organization
619
+
620
+ ### common.json - Shared UI
621
+ \`\`\`json
622
+ {
623
+ "buttons": {
624
+ "submit": "Submit",
625
+ "cancel": "Cancel",
626
+ "save": "Save",
627
+ "delete": "Delete",
628
+ "edit": "Edit"
629
+ },
630
+ "labels": {
631
+ "loading": "Loading...",
632
+ "error": "An error occurred",
633
+ "success": "Success!"
634
+ }
635
+ }
636
+ \`\`\`
637
+
638
+ ### auth.json - Authentication
639
+ \`\`\`json
640
+ {
641
+ "login": {
642
+ "title": "Sign In",
643
+ "email": "Email",
644
+ "password": "Password",
645
+ "submit": "Sign In",
646
+ "forgotPassword": "Forgot password?"
647
+ },
648
+ "register": {
649
+ "title": "Create Account",
650
+ "submit": "Sign Up"
651
+ },
652
+ "errors": {
653
+ "invalidCredentials": "Invalid email or password",
654
+ "emailTaken": "Email is already registered"
655
+ }
656
+ }
657
+ \`\`\`
658
+
659
+ ### errors.json - Error Messages
660
+ \`\`\`json
661
+ {
662
+ "network": {
663
+ "offline": "You are offline. Please check your connection.",
664
+ "timeout": "Request timed out. Please try again."
665
+ },
666
+ "validation": {
667
+ "required": "This field is required",
668
+ "email": "Please enter a valid email",
669
+ "minLength": "Must be at least {{min}} characters"
670
+ },
671
+ "http": {
672
+ "400": "Bad request",
673
+ "401": "Unauthorized",
674
+ "403": "Forbidden",
675
+ "404": "Not found",
676
+ "500": "Server error"
677
+ }
678
+ }
679
+ \`\`\`
680
+
681
+ ## Best Practices
682
+
683
+ ### 1. Use Descriptive Keys
684
+ \`\`\`json
685
+ // Good
686
+ {
687
+ "userProfile": {
688
+ "editButton": "Edit Profile",
689
+ "saveSuccess": "Profile saved successfully"
690
+ }
691
+ }
692
+
693
+ // Avoid
694
+ {
695
+ "btn1": "Edit Profile",
696
+ "msg1": "Profile saved successfully"
697
+ }
698
+ \`\`\`
699
+
700
+ ### 2. Group Related Translations
701
+ \`\`\`json
702
+ {
703
+ "checkout": {
704
+ "title": "Checkout",
705
+ "steps": {
706
+ "shipping": "Shipping",
707
+ "payment": "Payment",
708
+ "review": "Review"
709
+ },
710
+ "buttons": {
711
+ "next": "Continue",
712
+ "back": "Go Back",
713
+ "placeOrder": "Place Order"
714
+ }
715
+ }
716
+ }
717
+ \`\`\`
718
+
719
+ ### 3. Keep Keys Consistent Across Languages
720
+ All language files should have the same key structure:
721
+
722
+ \`\`\`json
723
+ // en/common.json
724
+ { "greeting": "Hello" }
725
+
726
+ // es/common.json
727
+ { "greeting": "Hola" }
728
+
729
+ // fr/common.json
730
+ { "greeting": "Bonjour" }
731
+ \`\`\`
732
+
733
+ ### 4. Add Comments with Default Values
734
+ The Babel plugin extracts \`defaultValue\` for documentation:
735
+
736
+ \`\`\`tsx
737
+ t('newFeature.title', { defaultValue: 'New Feature' })
738
+ \`\`\`
739
+
740
+ This appears in the report and helps translators understand context.
741
+ `,
742
+ "idealyst://translate/examples": `# Translation Examples
743
+
744
+ Complete code examples for common @idealyst/translate patterns.
745
+
746
+ ## Basic App Setup
747
+
748
+ \`\`\`tsx
749
+ // App.tsx
750
+ import { TranslateProvider } from '@idealyst/translate';
751
+ import en from './locales/en/common.json';
752
+ import es from './locales/es/common.json';
753
+
754
+ const config = {
755
+ defaultLanguage: 'en',
756
+ languages: ['en', 'es'],
757
+ resources: {
758
+ en: { common: en },
759
+ es: { common: es },
760
+ },
761
+ defaultNamespace: 'common',
762
+ };
763
+
764
+ export function App() {
765
+ return (
766
+ <TranslateProvider config={config}>
767
+ <Navigation />
768
+ </TranslateProvider>
769
+ );
770
+ }
771
+ \`\`\`
772
+
773
+ ## Component with Translations
774
+
775
+ \`\`\`tsx
776
+ // components/WelcomeScreen.tsx
777
+ import { View, Text, Button } from '@idealyst/components';
778
+ import { useTranslation } from '@idealyst/translate';
779
+
780
+ export function WelcomeScreen() {
781
+ const { t } = useTranslation('common');
782
+
783
+ return (
784
+ <View>
785
+ <Text variant="h1">{t('welcome.title')}</Text>
786
+ <Text>{t('welcome.subtitle')}</Text>
787
+ <Button onPress={() => {}}>
788
+ {t('buttons.getStarted')}
789
+ </Button>
790
+ </View>
791
+ );
792
+ }
793
+ \`\`\`
794
+
795
+ ## Language Switcher Component
796
+
797
+ \`\`\`tsx
798
+ // components/LanguageSwitcher.tsx
799
+ import { Select } from '@idealyst/components';
800
+ import { useLanguage } from '@idealyst/translate';
801
+
802
+ export function LanguageSwitcher() {
803
+ const { language, languages, setLanguage, getDisplayName } = useLanguage();
804
+
805
+ const options = languages.map((lang) => ({
806
+ value: lang,
807
+ label: getDisplayName(lang),
808
+ }));
809
+
810
+ return (
811
+ <Select
812
+ value={language}
813
+ options={options}
814
+ onChange={(value) => setLanguage(value)}
815
+ label="Language"
816
+ />
817
+ );
818
+ }
819
+ \`\`\`
820
+
821
+ ## Form with Validation Messages
822
+
823
+ \`\`\`tsx
824
+ // components/LoginForm.tsx
825
+ import { View, Input, Button, Text } from '@idealyst/components';
826
+ import { useTranslation } from '@idealyst/translate';
827
+ import { useState } from 'react';
828
+
829
+ export function LoginForm() {
830
+ const { t } = useTranslation('auth');
831
+ const [error, setError] = useState<string | null>(null);
832
+
833
+ const handleSubmit = async () => {
834
+ try {
835
+ // ... login logic
836
+ } catch (e) {
837
+ setError(t('errors.invalidCredentials'));
838
+ }
839
+ };
840
+
841
+ return (
842
+ <View>
843
+ <Text variant="h2">{t('login.title')}</Text>
844
+
845
+ <Input
846
+ label={t('login.email')}
847
+ placeholder={t('login.emailPlaceholder')}
848
+ keyboardType="email-address"
849
+ />
850
+
851
+ <Input
852
+ label={t('login.password')}
853
+ placeholder={t('login.passwordPlaceholder')}
854
+ secureTextEntry
855
+ />
856
+
857
+ {error && <Text intent="error">{error}</Text>}
858
+
859
+ <Button onPress={handleSubmit}>
860
+ {t('login.submit')}
861
+ </Button>
862
+ </View>
863
+ );
864
+ }
865
+ \`\`\`
866
+
867
+ ## Pluralization Example
868
+
869
+ \`\`\`tsx
870
+ // components/NotificationBadge.tsx
871
+ import { Badge } from '@idealyst/components';
872
+ import { useTranslation } from '@idealyst/translate';
873
+
874
+ interface Props {
875
+ count: number;
876
+ }
877
+
878
+ export function NotificationBadge({ count }: Props) {
879
+ const { t } = useTranslation('common');
880
+
881
+ if (count === 0) return null;
882
+
883
+ return (
884
+ <Badge intent="primary">
885
+ {t('notifications.count', { count })}
886
+ </Badge>
887
+ );
888
+ }
889
+
890
+ // Translation file:
891
+ // {
892
+ // "notifications": {
893
+ // "count": "{{count}} notification",
894
+ // "count_plural": "{{count}} notifications"
895
+ // }
896
+ // }
897
+ \`\`\`
898
+
899
+ ## Rich Text with Trans Component
900
+
901
+ \`\`\`tsx
902
+ // components/TermsAgreement.tsx
903
+ import { View, Text, Checkbox } from '@idealyst/components';
904
+ import { Trans, useTranslation } from '@idealyst/translate';
905
+ import { Link } from '@idealyst/navigation';
906
+ import { useState } from 'react';
907
+
908
+ export function TermsAgreement() {
909
+ const { t } = useTranslation('auth');
910
+ const [agreed, setAgreed] = useState(false);
911
+
912
+ return (
913
+ <View>
914
+ <Checkbox
915
+ checked={agreed}
916
+ onChange={setAgreed}
917
+ label={
918
+ <Trans
919
+ i18nKey="auth.termsAgreement"
920
+ components={{
921
+ terms: <Link to="/terms" />,
922
+ privacy: <Link to="/privacy" />,
923
+ }}
924
+ />
925
+ }
926
+ />
927
+ </View>
928
+ );
929
+ }
930
+
931
+ // Translation file:
932
+ // {
933
+ // "termsAgreement": "I agree to the <terms>Terms of Service</terms> and <privacy>Privacy Policy</privacy>"
934
+ // }
935
+ \`\`\`
936
+
937
+ ## Persisting Language Preference
938
+
939
+ \`\`\`tsx
940
+ // hooks/usePersistedLanguage.ts
941
+ import { useLanguage } from '@idealyst/translate';
942
+ import { useEffect } from 'react';
943
+ import AsyncStorage from '@react-native-async-storage/async-storage';
944
+
945
+ const LANGUAGE_KEY = '@app/language';
946
+
947
+ export function usePersistedLanguage() {
948
+ const { language, setLanguage } = useLanguage();
949
+
950
+ // Load saved language on mount
951
+ useEffect(() => {
952
+ AsyncStorage.getItem(LANGUAGE_KEY).then((saved) => {
953
+ if (saved) setLanguage(saved);
954
+ });
955
+ }, []);
956
+
957
+ // Save language when changed
958
+ useEffect(() => {
959
+ AsyncStorage.setItem(LANGUAGE_KEY, language);
960
+ }, [language]);
961
+
962
+ return { language, setLanguage };
963
+ }
964
+ \`\`\`
965
+
966
+ ## Multiple Namespaces
967
+
968
+ \`\`\`tsx
969
+ // components/UserProfile.tsx
970
+ import { useTranslation } from '@idealyst/translate';
971
+
972
+ export function UserProfile() {
973
+ // Load multiple namespaces
974
+ const { t } = useTranslation(['common', 'user']);
975
+
976
+ return (
977
+ <View>
978
+ {/* Use namespace prefix */}
979
+ <Text variant="h1">{t('user:profile.title')}</Text>
980
+ <Button>{t('common:buttons.edit')}</Button>
981
+ </View>
982
+ );
983
+ }
984
+ \`\`\`
985
+
986
+ ## Date and Number Formatting
987
+
988
+ \`\`\`tsx
989
+ // components/OrderSummary.tsx
990
+ import { View, Text } from '@idealyst/components';
991
+ import { useTranslation, useLanguage } from '@idealyst/translate';
992
+
993
+ interface Props {
994
+ total: number;
995
+ orderDate: Date;
996
+ }
997
+
998
+ export function OrderSummary({ total, orderDate }: Props) {
999
+ const { t } = useTranslation('orders');
1000
+ const { language } = useLanguage();
1001
+
1002
+ // Format based on current language
1003
+ const formattedTotal = new Intl.NumberFormat(language, {
1004
+ style: 'currency',
1005
+ currency: 'USD',
1006
+ }).format(total);
1007
+
1008
+ const formattedDate = new Intl.DateTimeFormat(language, {
1009
+ dateStyle: 'long',
1010
+ }).format(orderDate);
1011
+
1012
+ return (
1013
+ <View>
1014
+ <Text>{t('summary.total', { amount: formattedTotal })}</Text>
1015
+ <Text>{t('summary.date', { date: formattedDate })}</Text>
1016
+ </View>
1017
+ );
1018
+ }
1019
+
1020
+ // Translation file:
1021
+ // {
1022
+ // "summary": {
1023
+ // "total": "Total: {{amount}}",
1024
+ // "date": "Order placed on {{date}}"
1025
+ // }
1026
+ // }
1027
+ \`\`\`
1028
+ `,
1029
+ };
1030
+ //# sourceMappingURL=translate-guides.js.map