@ttoss/react-i18n 2.0.14 → 2.0.16

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.
Files changed (3) hide show
  1. package/README.md +623 -53
  2. package/dist/esm/index.js +20 -20
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -1,108 +1,678 @@
1
1
  # @ttoss/react-i18n
2
2
 
3
- **@ttoss/react-i18n** is a library that provides a way to internationalize your React application using ttoss ecosystem.
3
+ **@ttoss/react-i18n** is a React internationalization library built on [FormatJS](https://formatjs.io/) that seamlessly integrates with the ttoss ecosystem. It provides component-level i18n capabilities for translating text elements like buttons, labels, and headings, making your React applications accessible to global audiences.
4
+
5
+ ## Key Features
6
+
7
+ - **FormatJS Integration**: Built on industry-standard FormatJS with full ICU message format support
8
+ - **Dynamic Locale Loading**: Async loading of translation files with automatic caching
9
+ - **TypeScript Support**: Full TypeScript definitions for type-safe internationalization
10
+ - **Developer Experience**: Simple hooks and components for easy integration
11
+ - **ttoss Ecosystem**: Works seamlessly with other ttoss packages and tooling
12
+ - **Performance Optimized**: Efficient message loading and rendering with minimal overhead
13
+
14
+ ## When to Use
15
+
16
+ Choose `@ttoss/react-i18n` for **component-level internationalization** when you need to:
17
+
18
+ - Translate UI text elements (buttons, labels, form fields, notifications)
19
+ - Support multiple languages within React components
20
+ - Implement user language switching functionality
21
+ - Handle pluralization, number formatting, and date localization
22
+
23
+ For **routing-level internationalization** (SEO, CMS content, URL localization), consider Next.js built-in i18n features alongside this library.
4
24
 
5
25
  :::note
6
- You should declare your messages as describe in the [FormatJS](https://formatjs.io/docs/getting-started/message-declaration) documentation.
26
+ Declare your messages following [FormatJS message declaration guidelines](https://formatjs.io/docs/getting-started/message-declaration) for optimal extraction and compilation.
7
27
  :::
8
28
 
9
- ## Get Started
10
-
11
- ### Install @ttoss/react-i18n
29
+ ## Installation
12
30
 
13
31
  ```shell
14
32
  pnpm add @ttoss/react-i18n
15
33
  pnpm add -D @ttoss/i18n-cli
16
34
  ```
17
35
 
18
- To extract and compile your translations, check the [ttoss/i18n-cli](/docs/modules/packages/i18n-cli/) documentation.
36
+ The `@ttoss/i18n-cli` package handles message extraction and compilation. See the [i18n-cli documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/) for complete workflow setup.
19
37
 
20
- ## Examples of use
38
+ ## Quick Start
21
39
 
22
- ### index.tsx
40
+ ### 1. Provider Setup
23
41
 
24
- Import the `I18nProvider` and wrap your application with it. Add to it a function called `loadLocaleData` to load all the translation data.
42
+ Wrap your application with `I18nProvider` and configure locale data loading:
25
43
 
26
- ```tsx title="src/index.tsx"
44
+ ```tsx title="src/main.tsx"
45
+ import React from 'react';
46
+ import ReactDOM from 'react-dom/client';
27
47
  import { I18nProvider, LoadLocaleData } from '@ttoss/react-i18n';
48
+ import App from './App';
28
49
 
29
50
  const loadLocaleData: LoadLocaleData = async (locale) => {
30
51
  switch (locale) {
31
52
  case 'pt-BR':
32
- return import('../i18n/compiled/pt-BR.json');
53
+ return (await import('../i18n/compiled/pt-BR.json')).default;
54
+ case 'es':
55
+ return (await import('../i18n/compiled/es.json')).default;
33
56
  default:
34
- return import('../i18n/compiled/en.json');
57
+ return (await import('../i18n/compiled/en.json')).default;
35
58
  }
36
59
  };
37
60
 
38
- ReactDOM.render(
39
- <I18nProvider
40
- locale={window.navigator.language}
41
- loadLocaleData={loadLocaleData}
42
- >
61
+ ReactDOM.createRoot(document.getElementById('root')!).render(
62
+ <I18nProvider locale={navigator.language} loadLocaleData={loadLocaleData}>
43
63
  <App />
44
- </I18nProvider>,
45
- document.getElementById('root')
64
+ </I18nProvider>
46
65
  );
47
66
  ```
48
67
 
49
- ### App.tsx
68
+ ### 2. Component Usage
50
69
 
51
- Then import the useI18n hook and extract the intl, to get access to the `formatMessage` function and many others (using `defineMessages` is optional).
70
+ Use the `useI18n` hook to access internationalization features:
52
71
 
53
72
  ```tsx title="src/App.tsx"
54
- import { useI18n, defineMessages } from '@ttoss/react-i18n';
73
+ import React, { useState } from 'react';
74
+ import { useI18n } from '@ttoss/react-i18n';
55
75
 
56
- const messages = defineMessages({
57
- myNameIs: {
58
- description: 'My name is',
59
- defaultValue: 'My name is {name}',
60
- },
76
+ export default function App() {
77
+ const { intl, setLocale, locale } = useI18n();
78
+ const [name, setName] = useState('User');
79
+
80
+ const toggleLanguage = () => {
81
+ setLocale(locale === 'en' ? 'pt-BR' : 'en');
82
+ };
83
+
84
+ return (
85
+ <div>
86
+ <h1>
87
+ {intl.formatMessage(
88
+ {
89
+ description: 'Welcome message',
90
+ defaultMessage: 'Welcome, {name}!',
91
+ },
92
+ { name }
93
+ )}
94
+ </h1>
95
+ <input
96
+ value={name}
97
+ onChange={(e) => setName(e.target.value)}
98
+ placeholder="Enter your name"
99
+ />
100
+ <button onClick={toggleLanguage}>
101
+ {intl.formatMessage({
102
+ description: 'Change language button',
103
+ defaultMessage: 'Change Language',
104
+ })}
105
+ </button>
106
+ <p>Current locale: {locale}</p>
107
+ </div>
108
+ );
109
+ }
110
+ ```
111
+
112
+ ## Framework Integration
113
+
114
+ ### Vite Configuration
115
+
116
+ Configure Vite to properly handle message extraction. Choose between Babel or SWC based on your setup:
117
+
118
+ #### Option 1: Using Babel (with @ttoss/config)
119
+
120
+ ```ts title="vite.config.ts"
121
+ import { defineConfig } from 'vite';
122
+ import react from '@vitejs/plugin-react';
123
+ import { babelConfig } from '@ttoss/config';
124
+
125
+ export default defineConfig({
126
+ plugins: [
127
+ react({
128
+ babel: {
129
+ plugins: babelConfig().plugins,
130
+ },
131
+ }),
132
+ ],
133
+ });
134
+ ```
135
+
136
+ #### Option 2: Using Babel (manual configuration)
137
+
138
+ First, install the Babel plugin:
139
+
140
+ ```shell
141
+ pnpm add -D babel-plugin-formatjs
142
+ ```
143
+
144
+ Then configure Vite:
145
+
146
+ ```ts title="vite.config.ts"
147
+ import { defineConfig } from 'vite';
148
+ import react from '@vitejs/plugin-react';
149
+
150
+ export default defineConfig({
151
+ plugins: [
152
+ react({
153
+ babel: {
154
+ plugins: [
155
+ [
156
+ 'formatjs',
157
+ {
158
+ idInterpolationPattern: '[sha512:contenthash:base64:6]',
159
+ ast: true,
160
+ },
161
+ ],
162
+ ],
163
+ },
164
+ }),
165
+ ],
166
+ });
167
+ ```
168
+
169
+ #### Option 3: Using SWC
170
+
171
+ First, install the SWC plugin:
172
+
173
+ ```shell
174
+ pnpm add -D @swc/plugin-formatjs
175
+ ```
176
+
177
+ Then configure Vite with SWC:
178
+
179
+ ```ts title="vite.config.ts"
180
+ import react from '@vitejs/plugin-react-swc';
181
+ import { defineConfig } from 'vite';
182
+
183
+ export default defineConfig({
184
+ plugins: [
185
+ react({
186
+ plugins: [
187
+ [
188
+ '@swc/plugin-formatjs',
189
+ {
190
+ idInterpolationPattern: '[sha512:contenthash:base64:6]',
191
+ ast: true,
192
+ },
193
+ ],
194
+ ],
195
+ }),
196
+ ],
61
197
  });
198
+ ```
199
+
200
+ #### Configuration Options
201
+
202
+ - **`idInterpolationPattern`**: Generates unique, deterministic IDs for messages using content hash
203
+ - **`ast`**: Enables AST-based extraction for better performance and accuracy
204
+
205
+ For more configuration options, see:
206
+
207
+ - [Babel plugin documentation](https://formatjs.github.io/docs/tooling/babel-plugin/)
208
+ - [SWC plugin documentation](https://www.npmjs.com/package/@swc/plugin-formatjs)
209
+
210
+ ### Next.js Setup
211
+
212
+ For Next.js applications, configure the provider in `_app.tsx`:
213
+
214
+ ```tsx title="pages/_app.tsx"
215
+ import { I18nProvider, LoadLocaleData } from '@ttoss/react-i18n';
216
+ import { useRouter } from 'next/router';
217
+ import type { AppProps } from 'next/app';
62
218
 
63
- const App = () => {
64
- const { intl, setLocale } = useI18n();
219
+ const loadLocaleData: LoadLocaleData = async (locale) => {
220
+ switch (locale) {
221
+ case 'pt-BR':
222
+ return (await import('../../i18n/compiled/pt-BR.json')).default;
223
+ case 'es':
224
+ return (await import('../../i18n/compiled/es.json')).default;
225
+ default:
226
+ return (await import('../../i18n/compiled/en.json')).default;
227
+ }
228
+ };
65
229
 
66
- const [name, setName] = React.useState('Rayza');
230
+ export default function MyApp({ Component, pageProps }: AppProps) {
231
+ const { locale } = useRouter();
67
232
 
68
233
  return (
69
- <div>
70
- <div>
71
- <button onClick={() => setLocale('en-US')}>en-US</button>
234
+ <I18nProvider locale={locale} loadLocaleData={loadLocaleData}>
235
+ <Component {...pageProps} />
236
+ </I18nProvider>
237
+ );
238
+ }
239
+ ```
240
+
241
+ ## Advanced Usage
242
+
243
+ ### FormattedMessage Component
244
+
245
+ Use `FormattedMessage` for declarative message rendering:
72
246
 
73
- <button onClick={() => setLocale('pt-BR')}>pt-BR</button>
74
- </div>
247
+ ```tsx
248
+ import { FormattedMessage } from '@ttoss/react-i18n';
75
249
 
76
- <input value={name} onChange={(e) => setName(e.target.value)} />
250
+ function UserStats({ userCount, lastSeen }) {
251
+ return (
252
+ <div>
253
+ <FormattedMessage
254
+ description="Number of users"
255
+ defaultMessage="{count, plural, =0 {No users} =1 {One user} other {# users}}"
256
+ values={{ count: userCount }}
257
+ />
258
+ <FormattedMessage
259
+ description="Last seen timestamp"
260
+ defaultMessage="Last seen: {timestamp, date, short}"
261
+ values={{ timestamp: lastSeen }}
262
+ />
263
+ </div>
264
+ );
265
+ }
266
+ ```
267
+
268
+ :::warning Library Development
269
+ When creating **reusable libraries** that use this package, prefer `intl.formatMessage` over `FormattedMessage` component. During the build process, `FormattedMessage` gets transformed into JSX syntax like `return /* @__PURE__ */jsx(FormattedMessage, { defaultMessage: "..." })`, which prevents the message extraction tool from properly detecting and generating IDs for the messages.
77
270
 
78
- <h3>{intl.formatMessage(messages.myNameIs, { name })}</h3>
271
+ ```tsx
272
+ // ✅ Good for libraries - extracts correctly
273
+ function MyLibraryComponent() {
274
+ const { intl } = useI18n();
275
+ return (
276
+ <div>
277
+ {intl.formatMessage({
278
+ description: 'Library message',
279
+ defaultMessage: 'This message will be extracted correctly',
280
+ })}
79
281
  </div>
80
282
  );
81
- };
283
+ }
82
284
 
83
- export default App;
285
+ // Avoid in libraries - extraction may fail
286
+ function MyLibraryComponent() {
287
+ return (
288
+ <FormattedMessage
289
+ description="Library message"
290
+ defaultMessage="This may not extract properly in built libraries"
291
+ />
292
+ );
293
+ }
84
294
  ```
85
295
 
86
- ### Configuring Vite
296
+ :::
87
297
 
88
- In order to inject the i18n id's properly on the code, configure the `plugins` section of `vite.config.ts` according to this:
298
+ ### Error Handling
89
299
 
90
- ```ts
91
- import { babelConfig } from '@ttoss/config';
300
+ Handle translation errors gracefully:
92
301
 
93
- export default defineConfig(async () => {
94
- return {
95
- // ...
302
+ ```tsx
303
+ import { I18nProvider } from '@ttoss/react-i18n';
96
304
 
97
- plugins: [
98
- react({
99
- babel: {
100
- plugins: babelConfig().plugins,
305
+ function App() {
306
+ const handleTranslationError = (error: Error) => {
307
+ console.warn('Translation error:', error.message);
308
+ // Log to error tracking service
309
+ };
310
+
311
+ return (
312
+ <I18nProvider
313
+ locale="en"
314
+ loadLocaleData={loadLocaleData}
315
+ onError={handleTranslationError}
316
+ >
317
+ <MyApp />
318
+ </I18nProvider>
319
+ );
320
+ }
321
+ ```
322
+
323
+ ### Rich Text Formatting
324
+
325
+ Format messages with embedded components:
326
+
327
+ ```tsx
328
+ import { useI18n } from '@ttoss/react-i18n';
329
+
330
+ function SignupForm() {
331
+ const { intl } = useI18n();
332
+
333
+ return (
334
+ <p>
335
+ {intl.formatMessage(
336
+ {
337
+ description: 'Terms and conditions',
338
+ defaultMessage:
339
+ 'By signing up, you agree to our {termsLink} and {privacyLink}.',
101
340
  },
102
- }),
103
- ],
341
+ {
342
+ termsLink: <a href="/terms">Terms of Service</a>,
343
+ privacyLink: <a href="/privacy">Privacy Policy</a>,
344
+ }
345
+ )}
346
+ </p>
347
+ );
348
+ }
349
+ ```
350
+
351
+ ### Dynamic Locale Loading
352
+
353
+ Load locales based on user preferences:
354
+
355
+ ```tsx
356
+ import { useI18n } from '@ttoss/react-i18n';
357
+
358
+ function LanguageSelector() {
359
+ const { setLocale, locale } = useI18n();
360
+
361
+ const languages = [
362
+ { code: 'en', name: 'English' },
363
+ { code: 'pt-BR', name: 'Português' },
364
+ { code: 'es', name: 'Español' },
365
+ ];
366
+
367
+ const handleLanguageChange = async (newLocale: string) => {
368
+ // Persist user choice
369
+ localStorage.setItem('preferredLocale', newLocale);
370
+ setLocale(newLocale);
104
371
  };
105
372
 
106
- // ...
373
+ return (
374
+ <select
375
+ value={locale}
376
+ onChange={(e) => handleLanguageChange(e.target.value)}
377
+ >
378
+ {languages.map((lang) => (
379
+ <option key={lang.code} value={lang.code}>
380
+ {lang.name}
381
+ </option>
382
+ ))}
383
+ </select>
384
+ );
385
+ }
386
+ ```
387
+
388
+ ## API Reference
389
+
390
+ ### I18nProvider
391
+
392
+ Main provider component that configures internationalization context.
393
+
394
+ **Props:**
395
+
396
+ - `locale?: string` - Initial locale (defaults to browser language)
397
+ - `loadLocaleData?: LoadLocaleData` - Function to load translation data
398
+ - `onError?: (error: Error) => void` - Error handler for translation issues
399
+ - `children: ReactNode` - Child components
400
+
401
+ ```tsx
402
+ type LoadLocaleData = (locale: string) => Promise<Messages> | Messages;
403
+ type Messages = Record<string, string> | Record<string, MessageFormatElement[]>;
404
+ ```
405
+
406
+ ### useI18n Hook
407
+
408
+ Returns internationalization utilities and state.
409
+
410
+ **Returns:**
411
+
412
+ ```tsx
413
+ {
414
+ intl: IntlShape; // FormatJS intl object
415
+ locale: string; // Current locale
416
+ defaultLocale: string; // Default locale ('en')
417
+ setLocale: (locale: string) => void; // Change locale function
418
+ messages?: Messages; // Current translation messages
419
+ }
420
+ ```
421
+
422
+ **Example:**
423
+
424
+ ```tsx
425
+ const { intl, locale, setLocale } = useI18n();
426
+
427
+ // Format messages
428
+ const greeting = intl.formatMessage({
429
+ description: 'Simple greeting',
430
+ defaultMessage: 'Hello!',
431
+ });
432
+
433
+ // Format with variables
434
+ const welcome = intl.formatMessage(
435
+ {
436
+ description: 'Welcome message with name',
437
+ defaultMessage: 'Welcome, {name}!',
438
+ },
439
+ { name: 'John' }
440
+ );
441
+
442
+ // Format numbers and dates
443
+ const price = intl.formatNumber(29.99, { style: 'currency', currency: 'USD' });
444
+ const date = intl.formatDate(new Date(), { dateStyle: 'medium' });
445
+ ```
446
+
447
+ ### defineMessages / defineMessage
448
+
449
+ Type-safe message definition utilities from FormatJS.
450
+
451
+ ```tsx
452
+ import { defineMessages, defineMessage } from '@ttoss/react-i18n';
453
+
454
+ // Single message (recommended pattern)
455
+ const errorMessage = defineMessage({
456
+ description: 'Generic error message',
457
+ defaultMessage: 'Something went wrong. Please try again.',
458
+ });
459
+
460
+ // Multiple messages (alternative approach)
461
+ const messages = defineMessages({
462
+ title: {
463
+ description: 'Page title',
464
+ defaultMessage: 'My Application',
465
+ },
466
+ subtitle: {
467
+ description: 'Page subtitle',
468
+ defaultMessage: 'Welcome to our platform',
469
+ },
107
470
  });
471
+
472
+ // Usage in component
473
+ function MyComponent() {
474
+ const { intl } = useI18n();
475
+ return <div>{intl.formatMessage(errorMessage)}</div>;
476
+ }
108
477
  ```
478
+
479
+ :::note
480
+ The current ttoss pattern is to define messages inline within components rather than using `defineMessages`. This approach provides better co-location and reduces the need for separate message definitions.
481
+ :::
482
+
483
+ ### FormattedMessage
484
+
485
+ Component for declarative message rendering.
486
+
487
+ **Props:**
488
+
489
+ - `id?: string` - Message ID (auto-generated if using defineMessage)
490
+ - `defaultMessage: string` - Default message text
491
+ - `description?: string` - Message description for translators
492
+ - `values?: Record<string, any>` - Interpolation values
493
+
494
+ ```tsx
495
+ <FormattedMessage
496
+ description="Item count message"
497
+ defaultMessage="You have {count, plural, =0 {no items} =1 {one item} other {# items}}"
498
+ values={{ count: itemCount }}
499
+ />
500
+ ```
501
+
502
+ ## Best Practices
503
+
504
+ ### Message Organization
505
+
506
+ Structure your messages for maintainability:
507
+
508
+ ```tsx
509
+ // Inline messages with components (recommended ttoss pattern)
510
+ function AuthComponent() {
511
+ const { intl } = useI18n();
512
+
513
+ return (
514
+ <div>
515
+ <h1>
516
+ {intl.formatMessage({
517
+ description: 'Login page title',
518
+ defaultMessage: 'Sign In',
519
+ })}
520
+ </h1>
521
+ <button>
522
+ {intl.formatMessage({
523
+ description: 'Login submit button',
524
+ defaultMessage: 'Log In',
525
+ })}
526
+ </button>
527
+ <a href="/forgot-password">
528
+ {intl.formatMessage({
529
+ description: 'Forgot password link',
530
+ defaultMessage: 'Forgot your password?',
531
+ })}
532
+ </a>
533
+ </div>
534
+ );
535
+ }
536
+
537
+ // For reusable messages across components, you can still use defineMessage
538
+ import { defineMessage } from '@ttoss/react-i18n';
539
+
540
+ const successMessage = defineMessage({
541
+ description: 'Success message when user profile is updated',
542
+ defaultMessage: 'Your profile has been successfully updated.',
543
+ });
544
+
545
+ function ProfileForm() {
546
+ const { intl } = useI18n();
547
+
548
+ const handleSuccess = () => {
549
+ toast.success(intl.formatMessage(successMessage));
550
+ };
551
+
552
+ // ... rest of component
553
+ }
554
+ ```
555
+
556
+ ### Performance Optimization
557
+
558
+ Optimize loading and rendering:
559
+
560
+ ```tsx
561
+ // Lazy load locale data to reduce initial bundle size
562
+ const loadLocaleData: LoadLocaleData = async (locale) => {
563
+ const localeModule = await import(`../i18n/compiled/${locale}.json`);
564
+ return localeModule.default;
565
+ };
566
+
567
+ // Use React.memo for components with many translated strings
568
+ const TranslatedComponent = React.memo(function TranslatedComponent({ data }) {
569
+ const { intl } = useI18n();
570
+
571
+ return (
572
+ <div>
573
+ {data.map((item) => (
574
+ <div key={item.id}>
575
+ {intl.formatMessage(
576
+ {
577
+ description: 'Item title in list',
578
+ defaultMessage: 'Title: {title}',
579
+ },
580
+ { title: item.title }
581
+ )}
582
+ </div>
583
+ ))}
584
+ </div>
585
+ );
586
+ });
587
+ ```
588
+
589
+ ### Locale Detection
590
+
591
+ Implement intelligent locale detection:
592
+
593
+ ```tsx
594
+ function getInitialLocale(): string {
595
+ // 1. Check user preference from localStorage
596
+ const saved = localStorage.getItem('preferredLocale');
597
+ if (saved) return saved;
598
+
599
+ // 2. Check URL parameters
600
+ const urlParams = new URLSearchParams(window.location.search);
601
+ const urlLocale = urlParams.get('locale');
602
+ if (urlLocale) return urlLocale;
603
+
604
+ // 3. Use browser language with fallback
605
+ const browserLocale = navigator.language;
606
+ const supportedLocales = ['en', 'pt-BR', 'es'];
607
+
608
+ return supportedLocales.includes(browserLocale) ? browserLocale : 'en';
609
+ }
610
+ ```
611
+
612
+ ## Troubleshooting
613
+
614
+ ### Common Issues
615
+
616
+ **Missing translation warnings:**
617
+
618
+ ```
619
+ MessageError: MISSING_TRANSLATION
620
+ ```
621
+
622
+ - Ensure all locales have corresponding translation files
623
+ - Check that message IDs match between code and translation files
624
+ - Use `onError` prop to handle gracefully
625
+
626
+ **Babel plugin not working:**
627
+
628
+ ```
629
+ Messages not being extracted during build
630
+ ```
631
+
632
+ - Verify `@ttoss/config` babel plugins are configured correctly
633
+ - Check that message definitions use inline `intl.formatMessage` calls
634
+ - Ensure babel configuration is applied to your build process
635
+
636
+ **Locale not switching:**
637
+
638
+ ```
639
+ setLocale called but UI doesn't update
640
+ ```
641
+
642
+ - Verify `loadLocaleData` function returns correct translation data
643
+ - Check browser console for loading errors
644
+ - Ensure `I18nProvider` is at the correct level in component tree
645
+
646
+ ### Development Tips
647
+
648
+ Enable verbose logging during development:
649
+
650
+ ```tsx
651
+ const loadLocaleData: LoadLocaleData = async (locale) => {
652
+ console.log(`Loading locale: ${locale}`);
653
+ try {
654
+ const data = (await import(`../i18n/compiled/${locale}.json`)).default;
655
+ console.log(`Loaded ${Object.keys(data).length} messages for ${locale}`);
656
+ return data;
657
+ } catch (error) {
658
+ console.error(`Failed to load locale ${locale}:`, error);
659
+ throw error;
660
+ }
661
+ };
662
+ ```
663
+
664
+ ## Related Resources
665
+
666
+ ### ttoss Ecosystem
667
+
668
+ - **[@ttoss/i18n-cli](https://ttoss.dev/docs/modules/packages/i18n-cli/)** - Extract and compile translations using FormatJS workflow
669
+ - **[@ttoss/forms](https://ttoss.dev/docs/modules/packages/forms/)** - Form components with built-in i18n support
670
+ - **[@ttoss/ui](https://ttoss.dev/docs/modules/packages/ui/)** - UI components that work seamlessly with react-i18n
671
+
672
+ ### External Resources
673
+
674
+ - **[FormatJS Documentation](https://formatjs.io/)** - Complete guide to ICU message format and FormatJS features
675
+ - **[ICU Message Format](https://unicode-org.github.io/icu/userguide/format_parse/messages/)** - Specification for message formatting
676
+ - **[Building a Multilingual Blog with Next.js and @ttoss/react-i18n](https://ttoss.dev/blog/2023/09/26/building-a-multilingual-blog-site-with-next.js-and-@ttoss-react-i18n)** - Comprehensive tutorial
677
+
678
+ This library enables efficient internationalization following FormatJS standards while integrating seamlessly with the ttoss development ecosystem. For complete workflow setup including message extraction and compilation, see the [@ttoss/i18n-cli documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/).
package/dist/esm/index.js CHANGED
@@ -1,4 +1,9 @@
1
1
  /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ var __defProp = Object.defineProperty;
3
+ var __name = (target, value) => __defProp(target, "name", {
4
+ value,
5
+ configurable: true
6
+ });
2
7
 
3
8
  // src/index.ts
4
9
  import { defineMessages, defineMessage, FormattedMessage } from "react-intl";
@@ -6,16 +11,15 @@ import { defineMessages, defineMessage, FormattedMessage } from "react-intl";
6
11
  // src/i18Provider.tsx
7
12
  import * as React from "react";
8
13
  import { IntlProvider } from "react-intl";
9
- import { Fragment, jsx } from "react/jsx-runtime";
10
14
  var DEFAULT_LOCALE = "en";
11
- var I18nConfigContext = React.createContext({
15
+ var I18nConfigContext = /* @__PURE__ */React.createContext({
12
16
  defaultLocale: DEFAULT_LOCALE,
13
17
  messages: {},
14
- setLocale: () => {
18
+ setLocale: /* @__PURE__ */__name(() => {
15
19
  return null;
16
- }
20
+ }, "setLocale")
17
21
  });
18
- var I18nProvider = ({
22
+ var I18nProvider = /* @__PURE__ */__name(({
19
23
  children,
20
24
  locale: initialLocale,
21
25
  loadLocaleData,
@@ -35,35 +39,31 @@ var I18nProvider = ({
35
39
  });
36
40
  }
37
41
  }, [loadLocaleData, locale]);
38
- return /* @__PURE__ */jsx(I18nConfigContext.Provider, {
42
+ return /* @__PURE__ */React.createElement(I18nConfigContext.Provider, {
39
43
  value: {
40
44
  locale,
41
45
  defaultLocale: DEFAULT_LOCALE,
42
46
  messages: messagesAndLocale.messages,
43
47
  setLocale,
44
48
  ...intlConfig
45
- },
46
- children: /* @__PURE__ */jsx(IntlProvider, {
47
- defaultLocale: DEFAULT_LOCALE,
48
- locale: messagesAndLocale.locale,
49
- messages: messagesAndLocale.messages,
50
- ...intlConfig,
51
- children: /* @__PURE__ */jsx(Fragment, {
52
- children
53
- })
54
- })
55
- });
56
- };
49
+ }
50
+ }, /* @__PURE__ */React.createElement(IntlProvider, {
51
+ defaultLocale: DEFAULT_LOCALE,
52
+ locale: messagesAndLocale.locale,
53
+ messages: messagesAndLocale.messages,
54
+ ...intlConfig
55
+ }, /* @__PURE__ */React.createElement(React.Fragment, null, children)));
56
+ }, "I18nProvider");
57
57
 
58
58
  // src/useI18n.ts
59
59
  import * as React2 from "react";
60
60
  import { useIntl } from "react-intl";
61
- var useI18n = () => {
61
+ var useI18n = /* @__PURE__ */__name(() => {
62
62
  const intl = useIntl();
63
63
  const config = React2.useContext(I18nConfigContext);
64
64
  return {
65
65
  ...config,
66
66
  intl
67
67
  };
68
- };
68
+ }, "useI18n");
69
69
  export { DEFAULT_LOCALE, FormattedMessage, I18nProvider, defineMessage, defineMessages, useI18n };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/react-i18n",
3
- "version": "2.0.14",
3
+ "version": "2.0.16",
4
4
  "license": "MIT",
5
5
  "author": "ttoss",
6
6
  "contributors": [
@@ -36,7 +36,7 @@
36
36
  "react": "^19.1.0",
37
37
  "tsup": "^8.5.0",
38
38
  "@ttoss/config": "^1.35.6",
39
- "@ttoss/i18n-cli": "^0.7.31",
39
+ "@ttoss/i18n-cli": "^0.7.32",
40
40
  "@ttoss/test-utils": "^2.1.26"
41
41
  },
42
42
  "keywords": [