next-i18n-lite 1.0.3
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/LICENSE +21 -0
- package/README.md +254 -0
- package/dist/index.d.mts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +20 -0
- package/dist/react/index.d.ts +20 -0
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +2 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/types-DrfIsMVB.d.mts +12 -0
- package/dist/types-DrfIsMVB.d.ts +12 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Your Name
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
next-i18n-lite
|
|
2
|
+
|
|
3
|
+
🌍 Lightweight internationalization (i18n) library for Next.js with TypeScript support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ TypeScript support with full type safety
|
|
8
|
+
- ✅ React Context API integration
|
|
9
|
+
- ✅ Automatic RTL support for Arabic.
|
|
10
|
+
- ✅ Nested translation keys with dot notation
|
|
11
|
+
- ✅ Dynamic parameter replacement
|
|
12
|
+
- ✅ localStorage persistence
|
|
13
|
+
- ✅ Browser language detection
|
|
14
|
+
- ✅ Zero dependencies (except React peer deps)
|
|
15
|
+
- ✅ Tree-shakeable
|
|
16
|
+
- ✅ Works with Next.js 13+ App Router
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install next-i18n-lite
|
|
22
|
+
# or
|
|
23
|
+
yarn add next-i18n-lite
|
|
24
|
+
# or
|
|
25
|
+
pnpm add next-i18n-lite
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
File Structure
|
|
31
|
+
create those files inside app
|
|
32
|
+
1- I18nBoundary.tsx (inside lib/)
|
|
33
|
+
2- LocaleSwitcher.tsx (inside components)
|
|
34
|
+
3- lang files inside lib/locales/en.ts and ar.ts
|
|
35
|
+
that's all :D
|
|
36
|
+
app/
|
|
37
|
+
├─ layout.tsx # Root layout
|
|
38
|
+
├─ globals.css # Global styles
|
|
39
|
+
├─ Header.tsx # Header component (contains nav + LocaleSwitcher)
|
|
40
|
+
├─ components/
|
|
41
|
+
│ └─ i18n/
|
|
42
|
+
│ └─ LocaleSwitcher.tsx # Language switch button
|
|
43
|
+
└─ lib/
|
|
44
|
+
├─ I18nBoundary.tsx # Client-only i18n wrapper
|
|
45
|
+
└─ locales/
|
|
46
|
+
├─ en.ts # English translations
|
|
47
|
+
└─ ar.ts # Arabic translations
|
|
48
|
+
### 1. Create translation files
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// lib/locales/en.ts
|
|
52
|
+
export const en = {
|
|
53
|
+
common: {
|
|
54
|
+
welcome: 'Welcome',
|
|
55
|
+
loading: 'Loading...',
|
|
56
|
+
},
|
|
57
|
+
product: {
|
|
58
|
+
addToCart: 'Add to Cart',
|
|
59
|
+
price: 'Price: ${amount}',
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// lib/locales/ar.ts
|
|
64
|
+
export const ar = {
|
|
65
|
+
common: {
|
|
66
|
+
welcome: 'مرحباً',
|
|
67
|
+
loading: 'جاري التحميل...',
|
|
68
|
+
},
|
|
69
|
+
product: {
|
|
70
|
+
addToCart: 'أضف إلى السلة',
|
|
71
|
+
price: 'السعر: ${amount}',
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
- ✅ feel free to deal with object:
|
|
76
|
+
```typescript
|
|
77
|
+
export const en = {
|
|
78
|
+
welcome: 'Welcome',
|
|
79
|
+
loading: 'Loading...',
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
### 2. Setup Provider (Next.js App Router)
|
|
83
|
+
|
|
84
|
+
#### I18nBoundary.tsx
|
|
85
|
+
```typescript
|
|
86
|
+
// lib/I18nBoundary.tsx
|
|
87
|
+
'use client';
|
|
88
|
+
|
|
89
|
+
import { ReactNode, useEffect, useState } from 'react';
|
|
90
|
+
import { I18nProvider } from 'next-i18n-lite/react';
|
|
91
|
+
|
|
92
|
+
import { en } from './locales/en';
|
|
93
|
+
import { ar } from './locales/ar';
|
|
94
|
+
|
|
95
|
+
const translations = { en, ar };
|
|
96
|
+
|
|
97
|
+
export function I18nBoundary({ children }: { children: ReactNode }) {
|
|
98
|
+
const [locale, setLocale] = useState<'en' | 'ar' | null>(null);
|
|
99
|
+
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
const saved = localStorage.getItem('locale');
|
|
102
|
+
setLocale(saved === 'ar' ? 'ar' : 'en');
|
|
103
|
+
}, []);
|
|
104
|
+
|
|
105
|
+
if (!locale) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return (
|
|
109
|
+
<I18nProvider translations={translations} defaultLocale={locale}>
|
|
110
|
+
{children}
|
|
111
|
+
</I18nProvider>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
just created it not to fall in 'use client' in layout.tsx while you cannot use it with Metadata and similar issues ^^
|
|
116
|
+
still may face issue for setLocale
|
|
117
|
+
- Error: Calling setState synchronously within an effect can trigger cascading renders
|
|
118
|
+
|
|
119
|
+
Fix: not actually fixed yet but if you don't like red flags in code just
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
123
|
+
```
|
|
124
|
+
yup! ignore it :D
|
|
125
|
+
```typescript
|
|
126
|
+
// app/layout.tsx
|
|
127
|
+
import { I18nBoundary } from "./lib/I18nBoundary";
|
|
128
|
+
|
|
129
|
+
export default function RootLayout({ children }) {
|
|
130
|
+
return (
|
|
131
|
+
<html>
|
|
132
|
+
<body>
|
|
133
|
+
<I18nBoundary>
|
|
134
|
+
{children}
|
|
135
|
+
</I18nBoundary>
|
|
136
|
+
</body>
|
|
137
|
+
</html>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
### 3. Create LocaleSwitcher.tsx
|
|
142
|
+
/components/ui/LocaleSwitcher.tsx (recommended)
|
|
143
|
+
also i provided 2 options:
|
|
144
|
+
- Choice 1: Single-click toggle button
|
|
145
|
+
- Choice 2:Hover dropdown list
|
|
146
|
+
|
|
147
|
+
you can ignore styling & lucide-react library both only for example ^^
|
|
148
|
+
```typescript
|
|
149
|
+
'use client';
|
|
150
|
+
import { Globe } from "lucide-react";
|
|
151
|
+
import { useI18n } from "next-i18n-lite/react";
|
|
152
|
+
import { useEffect, useState } from "react";
|
|
153
|
+
|
|
154
|
+
const languages = [
|
|
155
|
+
{ code: 'en', name: 'English' },
|
|
156
|
+
{ code: 'ar', name: 'العربية' },
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
export function LocaleSwitcher() {
|
|
160
|
+
const { locale, setLocale, isRTL } = useI18n();
|
|
161
|
+
const [mounted, setMounted] = useState(false);
|
|
162
|
+
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
165
|
+
setMounted(true);
|
|
166
|
+
}, []);
|
|
167
|
+
|
|
168
|
+
if (!mounted) return null;
|
|
169
|
+
|
|
170
|
+
// Toggle between languages on single click
|
|
171
|
+
const toggleLocale = () => {
|
|
172
|
+
const persist = locale === 'en' ? 'ar' : 'en';
|
|
173
|
+
setLocale(persist);
|
|
174
|
+
localStorage.setItem('locale', persist); // persist choice
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// Positioning
|
|
178
|
+
const dropdownPosition = isRTL ? 'left-0' : 'right-0';
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<div className="relative group inline-block">
|
|
182
|
+
{/* Choice 1: Single-click toggle button */}
|
|
183
|
+
<Globe color="white" onClick={toggleLocale} className="top-5 "/>
|
|
184
|
+
|
|
185
|
+
{/* Choice 2:Hover dropdown list */}
|
|
186
|
+
<div
|
|
187
|
+
className={`absolute ${dropdownPosition} mt-2 bg-card border border-border rounded-xl shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all z-50`}
|
|
188
|
+
>
|
|
189
|
+
{languages.map((lang) => (
|
|
190
|
+
<button
|
|
191
|
+
key={lang.code}
|
|
192
|
+
onClick={() => {
|
|
193
|
+
setLocale(lang.code);
|
|
194
|
+
localStorage.setItem('locale', lang.code);
|
|
195
|
+
}}
|
|
196
|
+
className={`w-full flex items-center gap-3 px-4 py-3 transition-colors first:rounded-t-xl last:rounded-b-xl
|
|
197
|
+
${locale === lang.code ? 'bg-primary/10 text-primary' : 'hover:bg-gray-600'}
|
|
198
|
+
`}
|
|
199
|
+
>
|
|
200
|
+
<span className="text-sm font-medium">{lang.name}</span>
|
|
201
|
+
</button>
|
|
202
|
+
))}
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
### 4. Use in Components
|
|
209
|
+
### `useI18n()`
|
|
210
|
+
const { t, locale, setLocale, isRTL } = useI18n();
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
- `t(key, params?)` - Translation function
|
|
214
|
+
- `locale` - Current locale
|
|
215
|
+
- `setLocale(locale)` - Change locale
|
|
216
|
+
- `isRTL` - Boolean indicating RTL direction
|
|
217
|
+
```typescript
|
|
218
|
+
'use client';
|
|
219
|
+
import { useI18n } from "next-i18n-lite/react";
|
|
220
|
+
|
|
221
|
+
export function page() {
|
|
222
|
+
const { t } = useI18n();
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<div>
|
|
226
|
+
<h1>{t('common.welcome')}</h1>
|
|
227
|
+
<p>{t('product.price', { amount: '99' })}</p>
|
|
228
|
+
</div>
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
and that's it!!!
|
|
233
|
+
## API Reference
|
|
234
|
+
|
|
235
|
+
### `useI18n()`
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
- `t(key, params?)` - Translation function
|
|
239
|
+
- `locale` - Current locale
|
|
240
|
+
- `setLocale(locale)` - Change locale
|
|
241
|
+
- `isRTL` - Boolean indicating RTL direction
|
|
242
|
+
|
|
243
|
+
## Compatibility
|
|
244
|
+
|
|
245
|
+
- ✅ Node.js >= 18
|
|
246
|
+
- ✅ React >= 18
|
|
247
|
+
- ✅ Next.js >= 13
|
|
248
|
+
- ✅ TypeScript >= 5
|
|
249
|
+
|
|
250
|
+
## contact
|
|
251
|
+
codex410@gmail.com
|
|
252
|
+
## License
|
|
253
|
+
|
|
254
|
+
MIT © IslamAbozeed
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { T as TranslationsRecord, L as Locale } from './types-DrfIsMVB.mjs';
|
|
2
|
+
export { I as I18nConfig, N as NestedTranslations } from './types-DrfIsMVB.mjs';
|
|
3
|
+
|
|
4
|
+
declare class I18n {
|
|
5
|
+
private locale;
|
|
6
|
+
private fallbackLocale;
|
|
7
|
+
private translations;
|
|
8
|
+
constructor(translations: TranslationsRecord, defaultLocale: Locale, fallbackLocale?: Locale);
|
|
9
|
+
private isValidLocale;
|
|
10
|
+
private getNestedValue;
|
|
11
|
+
t(key: string, params?: Record<string, string | number>): string;
|
|
12
|
+
setLocale(locale: Locale): void;
|
|
13
|
+
getLocale(): Locale;
|
|
14
|
+
isRTL(locale?: Locale): boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare function formatDate(date: Date, locale: string): string;
|
|
18
|
+
declare function formatNumber(num: number, locale: string): string;
|
|
19
|
+
declare function formatCurrency(amount: number, locale: string, currency?: string): string;
|
|
20
|
+
declare function pluralize(count: number, singular: string, plural: string): string;
|
|
21
|
+
|
|
22
|
+
export { I18n, Locale, TranslationsRecord, formatCurrency, formatDate, formatNumber, pluralize };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { T as TranslationsRecord, L as Locale } from './types-DrfIsMVB.js';
|
|
2
|
+
export { I as I18nConfig, N as NestedTranslations } from './types-DrfIsMVB.js';
|
|
3
|
+
|
|
4
|
+
declare class I18n {
|
|
5
|
+
private locale;
|
|
6
|
+
private fallbackLocale;
|
|
7
|
+
private translations;
|
|
8
|
+
constructor(translations: TranslationsRecord, defaultLocale: Locale, fallbackLocale?: Locale);
|
|
9
|
+
private isValidLocale;
|
|
10
|
+
private getNestedValue;
|
|
11
|
+
t(key: string, params?: Record<string, string | number>): string;
|
|
12
|
+
setLocale(locale: Locale): void;
|
|
13
|
+
getLocale(): Locale;
|
|
14
|
+
isRTL(locale?: Locale): boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare function formatDate(date: Date, locale: string): string;
|
|
18
|
+
declare function formatNumber(num: number, locale: string): string;
|
|
19
|
+
declare function formatCurrency(amount: number, locale: string, currency?: string): string;
|
|
20
|
+
declare function pluralize(count: number, singular: string, plural: string): string;
|
|
21
|
+
|
|
22
|
+
export { I18n, Locale, TranslationsRecord, formatCurrency, formatDate, formatNumber, pluralize };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var i=class{constructor(t,e,n){if(this.translations=t,this.locale=e,this.fallbackLocale=n||e,typeof window<"u"){let r=localStorage.getItem("i18n-locale");r&&this.isValidLocale(r)&&(this.locale=r);}}isValidLocale(t){return t in this.translations}getNestedValue(t,e){let n=e.split("."),r=t;for(let s of n){if(!r||typeof r=="string")return;r=r[s];}return typeof r=="string"?r:void 0}t(t,e){let n=this.getNestedValue(this.translations[this.locale],t);return n||(n=this.getNestedValue(this.translations[this.fallbackLocale],t)),n?(e&&Object.keys(e).forEach(r=>{n=n.replace(new RegExp(`\\$\\{${r}\\}`,"g"),String(e[r]));}),n):(console.warn(`Translation missing for key: ${t}`),t)}setLocale(t){this.isValidLocale(t)&&(this.locale=t,typeof window<"u"&&(localStorage.setItem("i18n-locale",t),document.documentElement.setAttribute("lang",t),document.documentElement.setAttribute("dir",this.isRTL(t)?"rtl":"ltr")));}getLocale(){return this.locale}isRTL(t){let e=["ar","he","fa","ur"],n=t||this.locale;return e.includes(n)}};function a(o,t){return new Intl.DateTimeFormat(t).format(o)}function l(o,t){return new Intl.NumberFormat(t).format(o)}function c(o,t,e="USD"){return new Intl.NumberFormat(t,{style:"currency",currency:e}).format(o)}function u(o,t,e){return o===1?t:e}exports.I18n=i;exports.formatCurrency=c;exports.formatDate=a;exports.formatNumber=l;exports.pluralize=u;//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/I18n.ts","../src/utils/formatters.ts"],"names":["I18n","translations","defaultLocale","fallbackLocale","savedLocale","locale","obj","path","keys","current","key","params","translation","param","rtlLocales","checkLocale","formatDate","date","formatNumber","num","formatCurrency","amount","currency","pluralize","count","singular","plural"],"mappings":"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","file":"index.js","sourcesContent":["import { Locale, NestedTranslations, TranslationsRecord } from '../types';\r\n\r\nexport class I18n {\r\n private locale: Locale;\r\n private fallbackLocale: Locale;\r\n private translations: TranslationsRecord;\r\n\r\n constructor(\r\n translations: TranslationsRecord,\r\n defaultLocale: Locale,\r\n fallbackLocale?: Locale\r\n ) {\r\n this.translations = translations;\r\n this.locale = defaultLocale;\r\n this.fallbackLocale = fallbackLocale || defaultLocale;\r\n\r\n if (typeof window !== 'undefined') {\r\n const savedLocale = localStorage.getItem('i18n-locale');\r\n if (savedLocale && this.isValidLocale(savedLocale)) {\r\n this.locale = savedLocale;\r\n }\r\n }\r\n }\r\n\r\n private isValidLocale(locale: string): boolean {\r\n return locale in this.translations;\r\n }\r\n\r\n private getNestedValue(\r\n obj: NestedTranslations,\r\n path: string\r\n ): string | undefined {\r\n const keys = path.split('.');\r\n let current: string | NestedTranslations | undefined = obj;\r\n\r\n for (const key of keys) {\r\n if (!current || typeof current === 'string') return undefined;\r\n current = current[key];\r\n }\r\n\r\n return typeof current === 'string' ? current : undefined;\r\n }\r\n\r\n t(key: string, params?: Record<string, string | number>): string {\r\n let translation = this.getNestedValue(this.translations[this.locale], key);\r\n\r\n if (!translation) {\r\n translation = this.getNestedValue(\r\n this.translations[this.fallbackLocale],\r\n key\r\n );\r\n }\r\n\r\n if (!translation) {\r\n console.warn(`Translation missing for key: ${key}`);\r\n return key;\r\n }\r\n\r\n if (params) {\r\n Object.keys(params).forEach((param) => {\r\n translation = translation!.replace(\r\n new RegExp(`\\\\$\\\\{${param}\\\\}`, 'g'),\r\n String(params[param])\r\n );\r\n });\r\n }\r\n\r\n return translation;\r\n }\r\n\r\n setLocale(locale: Locale): void {\r\n if (this.isValidLocale(locale)) {\r\n this.locale = locale;\r\n if (typeof window !== 'undefined') {\r\n localStorage.setItem('i18n-locale', locale);\r\n document.documentElement.setAttribute('lang', locale);\r\n document.documentElement.setAttribute(\r\n 'dir',\r\n this.isRTL(locale) ? 'rtl' : 'ltr'\r\n );\r\n }\r\n }\r\n }\r\n\r\n getLocale(): Locale {\r\n return this.locale;\r\n }\r\n\r\n isRTL(locale?: Locale): boolean {\r\n const rtlLocales = ['ar', 'he', 'fa', 'ur'];\r\n const checkLocale = locale || this.locale;\r\n return rtlLocales.includes(checkLocale);\r\n }\r\n}","export function formatDate(date: Date, locale: string): string {\r\n return new Intl.DateTimeFormat(locale).format(date);\r\n}\r\n\r\nexport function formatNumber(num: number, locale: string): string {\r\n return new Intl.NumberFormat(locale).format(num);\r\n}\r\n\r\nexport function formatCurrency(\r\n amount: number,\r\n locale: string,\r\n currency = 'USD'\r\n): string {\r\n return new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currency,\r\n }).format(amount);\r\n}\r\n\r\nexport function pluralize(\r\n count: number,\r\n singular: string,\r\n plural: string\r\n): string {\r\n return count === 1 ? singular : plural;\r\n}"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var i=class{constructor(t,e,n){if(this.translations=t,this.locale=e,this.fallbackLocale=n||e,typeof window<"u"){let r=localStorage.getItem("i18n-locale");r&&this.isValidLocale(r)&&(this.locale=r);}}isValidLocale(t){return t in this.translations}getNestedValue(t,e){let n=e.split("."),r=t;for(let s of n){if(!r||typeof r=="string")return;r=r[s];}return typeof r=="string"?r:void 0}t(t,e){let n=this.getNestedValue(this.translations[this.locale],t);return n||(n=this.getNestedValue(this.translations[this.fallbackLocale],t)),n?(e&&Object.keys(e).forEach(r=>{n=n.replace(new RegExp(`\\$\\{${r}\\}`,"g"),String(e[r]));}),n):(console.warn(`Translation missing for key: ${t}`),t)}setLocale(t){this.isValidLocale(t)&&(this.locale=t,typeof window<"u"&&(localStorage.setItem("i18n-locale",t),document.documentElement.setAttribute("lang",t),document.documentElement.setAttribute("dir",this.isRTL(t)?"rtl":"ltr")));}getLocale(){return this.locale}isRTL(t){let e=["ar","he","fa","ur"],n=t||this.locale;return e.includes(n)}};function a(o,t){return new Intl.DateTimeFormat(t).format(o)}function l(o,t){return new Intl.NumberFormat(t).format(o)}function c(o,t,e="USD"){return new Intl.NumberFormat(t,{style:"currency",currency:e}).format(o)}function u(o,t,e){return o===1?t:e}export{i as I18n,c as formatCurrency,a as formatDate,l as formatNumber,u as pluralize};//# sourceMappingURL=index.mjs.map
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/I18n.ts","../src/utils/formatters.ts"],"names":["I18n","translations","defaultLocale","fallbackLocale","savedLocale","locale","obj","path","keys","current","key","params","translation","param","rtlLocales","checkLocale","formatDate","date","formatNumber","num","formatCurrency","amount","currency","pluralize","count","singular","plural"],"mappings":"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","file":"index.mjs","sourcesContent":["import { Locale, NestedTranslations, TranslationsRecord } from '../types';\r\n\r\nexport class I18n {\r\n private locale: Locale;\r\n private fallbackLocale: Locale;\r\n private translations: TranslationsRecord;\r\n\r\n constructor(\r\n translations: TranslationsRecord,\r\n defaultLocale: Locale,\r\n fallbackLocale?: Locale\r\n ) {\r\n this.translations = translations;\r\n this.locale = defaultLocale;\r\n this.fallbackLocale = fallbackLocale || defaultLocale;\r\n\r\n if (typeof window !== 'undefined') {\r\n const savedLocale = localStorage.getItem('i18n-locale');\r\n if (savedLocale && this.isValidLocale(savedLocale)) {\r\n this.locale = savedLocale;\r\n }\r\n }\r\n }\r\n\r\n private isValidLocale(locale: string): boolean {\r\n return locale in this.translations;\r\n }\r\n\r\n private getNestedValue(\r\n obj: NestedTranslations,\r\n path: string\r\n ): string | undefined {\r\n const keys = path.split('.');\r\n let current: string | NestedTranslations | undefined = obj;\r\n\r\n for (const key of keys) {\r\n if (!current || typeof current === 'string') return undefined;\r\n current = current[key];\r\n }\r\n\r\n return typeof current === 'string' ? current : undefined;\r\n }\r\n\r\n t(key: string, params?: Record<string, string | number>): string {\r\n let translation = this.getNestedValue(this.translations[this.locale], key);\r\n\r\n if (!translation) {\r\n translation = this.getNestedValue(\r\n this.translations[this.fallbackLocale],\r\n key\r\n );\r\n }\r\n\r\n if (!translation) {\r\n console.warn(`Translation missing for key: ${key}`);\r\n return key;\r\n }\r\n\r\n if (params) {\r\n Object.keys(params).forEach((param) => {\r\n translation = translation!.replace(\r\n new RegExp(`\\\\$\\\\{${param}\\\\}`, 'g'),\r\n String(params[param])\r\n );\r\n });\r\n }\r\n\r\n return translation;\r\n }\r\n\r\n setLocale(locale: Locale): void {\r\n if (this.isValidLocale(locale)) {\r\n this.locale = locale;\r\n if (typeof window !== 'undefined') {\r\n localStorage.setItem('i18n-locale', locale);\r\n document.documentElement.setAttribute('lang', locale);\r\n document.documentElement.setAttribute(\r\n 'dir',\r\n this.isRTL(locale) ? 'rtl' : 'ltr'\r\n );\r\n }\r\n }\r\n }\r\n\r\n getLocale(): Locale {\r\n return this.locale;\r\n }\r\n\r\n isRTL(locale?: Locale): boolean {\r\n const rtlLocales = ['ar', 'he', 'fa', 'ur'];\r\n const checkLocale = locale || this.locale;\r\n return rtlLocales.includes(checkLocale);\r\n }\r\n}","export function formatDate(date: Date, locale: string): string {\r\n return new Intl.DateTimeFormat(locale).format(date);\r\n}\r\n\r\nexport function formatNumber(num: number, locale: string): string {\r\n return new Intl.NumberFormat(locale).format(num);\r\n}\r\n\r\nexport function formatCurrency(\r\n amount: number,\r\n locale: string,\r\n currency = 'USD'\r\n): string {\r\n return new Intl.NumberFormat(locale, {\r\n style: 'currency',\r\n currency,\r\n }).format(amount);\r\n}\r\n\r\nexport function pluralize(\r\n count: number,\r\n singular: string,\r\n plural: string\r\n): string {\r\n return count === 1 ? singular : plural;\r\n}"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { T as TranslationsRecord, L as Locale } from '../types-DrfIsMVB.mjs';
|
|
4
|
+
|
|
5
|
+
interface I18nContextType {
|
|
6
|
+
locale: Locale;
|
|
7
|
+
setLocale: (locale: Locale) => void;
|
|
8
|
+
t: (key: string, params?: Record<string, string | number>) => string;
|
|
9
|
+
isRTL: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface I18nProviderProps {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
translations: TranslationsRecord;
|
|
14
|
+
defaultLocale: Locale;
|
|
15
|
+
fallbackLocale?: Locale;
|
|
16
|
+
}
|
|
17
|
+
declare function I18nProvider({ children, translations, defaultLocale, fallbackLocale, }: I18nProviderProps): react_jsx_runtime.JSX.Element;
|
|
18
|
+
declare function useI18n(): I18nContextType;
|
|
19
|
+
|
|
20
|
+
export { I18nProvider, useI18n };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { T as TranslationsRecord, L as Locale } from '../types-DrfIsMVB.js';
|
|
4
|
+
|
|
5
|
+
interface I18nContextType {
|
|
6
|
+
locale: Locale;
|
|
7
|
+
setLocale: (locale: Locale) => void;
|
|
8
|
+
t: (key: string, params?: Record<string, string | number>) => string;
|
|
9
|
+
isRTL: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface I18nProviderProps {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
translations: TranslationsRecord;
|
|
14
|
+
defaultLocale: Locale;
|
|
15
|
+
fallbackLocale?: Locale;
|
|
16
|
+
}
|
|
17
|
+
declare function I18nProvider({ children, translations, defaultLocale, fallbackLocale, }: I18nProviderProps): react_jsx_runtime.JSX.Element;
|
|
18
|
+
declare function useI18n(): I18nContextType;
|
|
19
|
+
|
|
20
|
+
export { I18nProvider, useI18n };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');var a=class{constructor(e,o,n){if(this.translations=e,this.locale=o,this.fallbackLocale=n||o,typeof window<"u"){let t=localStorage.getItem("i18n-locale");t&&this.isValidLocale(t)&&(this.locale=t);}}isValidLocale(e){return e in this.translations}getNestedValue(e,o){let n=o.split("."),t=e;for(let s of n){if(!t||typeof t=="string")return;t=t[s];}return typeof t=="string"?t:void 0}t(e,o){let n=this.getNestedValue(this.translations[this.locale],e);return n||(n=this.getNestedValue(this.translations[this.fallbackLocale],e)),n?(o&&Object.keys(o).forEach(t=>{n=n.replace(new RegExp(`\\$\\{${t}\\}`,"g"),String(o[t]));}),n):(console.warn(`Translation missing for key: ${e}`),e)}setLocale(e){this.isValidLocale(e)&&(this.locale=e,typeof window<"u"&&(localStorage.setItem("i18n-locale",e),document.documentElement.setAttribute("lang",e),document.documentElement.setAttribute("dir",this.isRTL(e)?"rtl":"ltr")));}getLocale(){return this.locale}isRTL(e){let o=["ar","he","fa","ur"],n=e||this.locale;return o.includes(n)}};var d=react.createContext(void 0);function b({children:r,translations:e,defaultLocale:o,fallbackLocale:n}){let[t]=react.useState(()=>new a(e,o,n)),[s,f]=react.useState(t.getLocale()),[l,L]=react.useState(t.isRTL()),g=i=>{t.setLocale(i),f(i),L(t.isRTL(i));},m=(i,p)=>t.t(i,p);return react.useEffect(()=>{document.documentElement.setAttribute("dir",l?"rtl":"ltr"),document.documentElement.setAttribute("lang",s);},[s,l]),jsxRuntime.jsx(d.Provider,{value:{locale:s,setLocale:g,t:m,isRTL:l},children:r})}function u(){let r=react.useContext(d);if(!r)throw new Error("useI18n must be used within I18nProvider");return r}exports.I18nProvider=b;exports.useI18n=u;//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/I18n.ts","../../src/react/I18nProvider.tsx"],"names":["I18n","translations","defaultLocale","fallbackLocale","savedLocale","locale","obj","path","keys","current","key","params","translation","param","rtlLocales","checkLocale","I18nContext","createContext","I18nProvider","children","i18n","useState","setLocaleState","isRTL","setIsRTL","setLocale","newLocale","t","useEffect","jsx","useI18n","context","useContext"],"mappings":"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","file":"index.js","sourcesContent":["import { Locale, NestedTranslations, TranslationsRecord } from '../types';\r\n\r\nexport class I18n {\r\n private locale: Locale;\r\n private fallbackLocale: Locale;\r\n private translations: TranslationsRecord;\r\n\r\n constructor(\r\n translations: TranslationsRecord,\r\n defaultLocale: Locale,\r\n fallbackLocale?: Locale\r\n ) {\r\n this.translations = translations;\r\n this.locale = defaultLocale;\r\n this.fallbackLocale = fallbackLocale || defaultLocale;\r\n\r\n if (typeof window !== 'undefined') {\r\n const savedLocale = localStorage.getItem('i18n-locale');\r\n if (savedLocale && this.isValidLocale(savedLocale)) {\r\n this.locale = savedLocale;\r\n }\r\n }\r\n }\r\n\r\n private isValidLocale(locale: string): boolean {\r\n return locale in this.translations;\r\n }\r\n\r\n private getNestedValue(\r\n obj: NestedTranslations,\r\n path: string\r\n ): string | undefined {\r\n const keys = path.split('.');\r\n let current: string | NestedTranslations | undefined = obj;\r\n\r\n for (const key of keys) {\r\n if (!current || typeof current === 'string') return undefined;\r\n current = current[key];\r\n }\r\n\r\n return typeof current === 'string' ? current : undefined;\r\n }\r\n\r\n t(key: string, params?: Record<string, string | number>): string {\r\n let translation = this.getNestedValue(this.translations[this.locale], key);\r\n\r\n if (!translation) {\r\n translation = this.getNestedValue(\r\n this.translations[this.fallbackLocale],\r\n key\r\n );\r\n }\r\n\r\n if (!translation) {\r\n console.warn(`Translation missing for key: ${key}`);\r\n return key;\r\n }\r\n\r\n if (params) {\r\n Object.keys(params).forEach((param) => {\r\n translation = translation!.replace(\r\n new RegExp(`\\\\$\\\\{${param}\\\\}`, 'g'),\r\n String(params[param])\r\n );\r\n });\r\n }\r\n\r\n return translation;\r\n }\r\n\r\n setLocale(locale: Locale): void {\r\n if (this.isValidLocale(locale)) {\r\n this.locale = locale;\r\n if (typeof window !== 'undefined') {\r\n localStorage.setItem('i18n-locale', locale);\r\n document.documentElement.setAttribute('lang', locale);\r\n document.documentElement.setAttribute(\r\n 'dir',\r\n this.isRTL(locale) ? 'rtl' : 'ltr'\r\n );\r\n }\r\n }\r\n }\r\n\r\n getLocale(): Locale {\r\n return this.locale;\r\n }\r\n\r\n isRTL(locale?: Locale): boolean {\r\n const rtlLocales = ['ar', 'he', 'fa', 'ur'];\r\n const checkLocale = locale || this.locale;\r\n return rtlLocales.includes(checkLocale);\r\n }\r\n}","'use client';\r\n\r\nimport { createContext, useContext, useState, useEffect, ReactNode } from 'react';\r\nimport { I18n } from '../core/I18n';\r\nimport { Locale, TranslationsRecord } from '../types';\r\n\r\nexport interface I18nContextType {\r\n locale: Locale;\r\n setLocale: (locale: Locale) => void;\r\n t: (key: string, params?: Record<string, string | number>) => string;\r\n isRTL: boolean;\r\n}\r\n\r\nexport const I18nContext = createContext<I18nContextType | undefined>(undefined);\r\n\r\ninterface I18nProviderProps {\r\n children: ReactNode;\r\n translations: TranslationsRecord;\r\n defaultLocale: Locale;\r\n fallbackLocale?: Locale;\r\n}\r\n\r\nexport function I18nProvider({\r\n children,\r\n translations,\r\n defaultLocale,\r\n fallbackLocale,\r\n}: I18nProviderProps) {\r\n const [i18n] = useState(\r\n () => new I18n(translations, defaultLocale, fallbackLocale)\r\n );\r\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\r\n const [isRTL, setIsRTL] = useState(i18n.isRTL());\r\n\r\n const setLocale = (newLocale: Locale) => {\r\n i18n.setLocale(newLocale);\r\n setLocaleState(newLocale);\r\n setIsRTL(i18n.isRTL(newLocale));\r\n };\r\n\r\n const t = (key: string, params?: Record<string, string | number>) => {\r\n return i18n.t(key, params);\r\n };\r\n\r\n useEffect(() => {\r\n document.documentElement.setAttribute('dir', isRTL ? 'rtl' : 'ltr');\r\n document.documentElement.setAttribute('lang', locale);\r\n }, [locale, isRTL]);\r\n\r\n return (\r\n <I18nContext.Provider value={{ locale, setLocale, t, isRTL }}>\r\n {children}\r\n </I18nContext.Provider>\r\n );\r\n}\r\n\r\n// Export useI18n hook here as well\r\nexport function useI18n() {\r\n const context = useContext(I18nContext);\r\n if (!context) {\r\n throw new Error('useI18n must be used within I18nProvider');\r\n }\r\n return context;\r\n}"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {createContext,useState,useEffect,useContext}from'react';import {jsx}from'react/jsx-runtime';var a=class{constructor(e,o,n){if(this.translations=e,this.locale=o,this.fallbackLocale=n||o,typeof window<"u"){let t=localStorage.getItem("i18n-locale");t&&this.isValidLocale(t)&&(this.locale=t);}}isValidLocale(e){return e in this.translations}getNestedValue(e,o){let n=o.split("."),t=e;for(let s of n){if(!t||typeof t=="string")return;t=t[s];}return typeof t=="string"?t:void 0}t(e,o){let n=this.getNestedValue(this.translations[this.locale],e);return n||(n=this.getNestedValue(this.translations[this.fallbackLocale],e)),n?(o&&Object.keys(o).forEach(t=>{n=n.replace(new RegExp(`\\$\\{${t}\\}`,"g"),String(o[t]));}),n):(console.warn(`Translation missing for key: ${e}`),e)}setLocale(e){this.isValidLocale(e)&&(this.locale=e,typeof window<"u"&&(localStorage.setItem("i18n-locale",e),document.documentElement.setAttribute("lang",e),document.documentElement.setAttribute("dir",this.isRTL(e)?"rtl":"ltr")));}getLocale(){return this.locale}isRTL(e){let o=["ar","he","fa","ur"],n=e||this.locale;return o.includes(n)}};var d=createContext(void 0);function b({children:r,translations:e,defaultLocale:o,fallbackLocale:n}){let[t]=useState(()=>new a(e,o,n)),[s,f]=useState(t.getLocale()),[l,L]=useState(t.isRTL()),g=i=>{t.setLocale(i),f(i),L(t.isRTL(i));},m=(i,p)=>t.t(i,p);return useEffect(()=>{document.documentElement.setAttribute("dir",l?"rtl":"ltr"),document.documentElement.setAttribute("lang",s);},[s,l]),jsx(d.Provider,{value:{locale:s,setLocale:g,t:m,isRTL:l},children:r})}function u(){let r=useContext(d);if(!r)throw new Error("useI18n must be used within I18nProvider");return r}export{b as I18nProvider,u as useI18n};//# sourceMappingURL=index.mjs.map
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/I18n.ts","../../src/react/I18nProvider.tsx"],"names":["I18n","translations","defaultLocale","fallbackLocale","savedLocale","locale","obj","path","keys","current","key","params","translation","param","rtlLocales","checkLocale","I18nContext","createContext","I18nProvider","children","i18n","useState","setLocaleState","isRTL","setIsRTL","setLocale","newLocale","t","useEffect","jsx","useI18n","context","useContext"],"mappings":"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","file":"index.mjs","sourcesContent":["import { Locale, NestedTranslations, TranslationsRecord } from '../types';\r\n\r\nexport class I18n {\r\n private locale: Locale;\r\n private fallbackLocale: Locale;\r\n private translations: TranslationsRecord;\r\n\r\n constructor(\r\n translations: TranslationsRecord,\r\n defaultLocale: Locale,\r\n fallbackLocale?: Locale\r\n ) {\r\n this.translations = translations;\r\n this.locale = defaultLocale;\r\n this.fallbackLocale = fallbackLocale || defaultLocale;\r\n\r\n if (typeof window !== 'undefined') {\r\n const savedLocale = localStorage.getItem('i18n-locale');\r\n if (savedLocale && this.isValidLocale(savedLocale)) {\r\n this.locale = savedLocale;\r\n }\r\n }\r\n }\r\n\r\n private isValidLocale(locale: string): boolean {\r\n return locale in this.translations;\r\n }\r\n\r\n private getNestedValue(\r\n obj: NestedTranslations,\r\n path: string\r\n ): string | undefined {\r\n const keys = path.split('.');\r\n let current: string | NestedTranslations | undefined = obj;\r\n\r\n for (const key of keys) {\r\n if (!current || typeof current === 'string') return undefined;\r\n current = current[key];\r\n }\r\n\r\n return typeof current === 'string' ? current : undefined;\r\n }\r\n\r\n t(key: string, params?: Record<string, string | number>): string {\r\n let translation = this.getNestedValue(this.translations[this.locale], key);\r\n\r\n if (!translation) {\r\n translation = this.getNestedValue(\r\n this.translations[this.fallbackLocale],\r\n key\r\n );\r\n }\r\n\r\n if (!translation) {\r\n console.warn(`Translation missing for key: ${key}`);\r\n return key;\r\n }\r\n\r\n if (params) {\r\n Object.keys(params).forEach((param) => {\r\n translation = translation!.replace(\r\n new RegExp(`\\\\$\\\\{${param}\\\\}`, 'g'),\r\n String(params[param])\r\n );\r\n });\r\n }\r\n\r\n return translation;\r\n }\r\n\r\n setLocale(locale: Locale): void {\r\n if (this.isValidLocale(locale)) {\r\n this.locale = locale;\r\n if (typeof window !== 'undefined') {\r\n localStorage.setItem('i18n-locale', locale);\r\n document.documentElement.setAttribute('lang', locale);\r\n document.documentElement.setAttribute(\r\n 'dir',\r\n this.isRTL(locale) ? 'rtl' : 'ltr'\r\n );\r\n }\r\n }\r\n }\r\n\r\n getLocale(): Locale {\r\n return this.locale;\r\n }\r\n\r\n isRTL(locale?: Locale): boolean {\r\n const rtlLocales = ['ar', 'he', 'fa', 'ur'];\r\n const checkLocale = locale || this.locale;\r\n return rtlLocales.includes(checkLocale);\r\n }\r\n}","'use client';\r\n\r\nimport { createContext, useContext, useState, useEffect, ReactNode } from 'react';\r\nimport { I18n } from '../core/I18n';\r\nimport { Locale, TranslationsRecord } from '../types';\r\n\r\nexport interface I18nContextType {\r\n locale: Locale;\r\n setLocale: (locale: Locale) => void;\r\n t: (key: string, params?: Record<string, string | number>) => string;\r\n isRTL: boolean;\r\n}\r\n\r\nexport const I18nContext = createContext<I18nContextType | undefined>(undefined);\r\n\r\ninterface I18nProviderProps {\r\n children: ReactNode;\r\n translations: TranslationsRecord;\r\n defaultLocale: Locale;\r\n fallbackLocale?: Locale;\r\n}\r\n\r\nexport function I18nProvider({\r\n children,\r\n translations,\r\n defaultLocale,\r\n fallbackLocale,\r\n}: I18nProviderProps) {\r\n const [i18n] = useState(\r\n () => new I18n(translations, defaultLocale, fallbackLocale)\r\n );\r\n const [locale, setLocaleState] = useState<Locale>(i18n.getLocale());\r\n const [isRTL, setIsRTL] = useState(i18n.isRTL());\r\n\r\n const setLocale = (newLocale: Locale) => {\r\n i18n.setLocale(newLocale);\r\n setLocaleState(newLocale);\r\n setIsRTL(i18n.isRTL(newLocale));\r\n };\r\n\r\n const t = (key: string, params?: Record<string, string | number>) => {\r\n return i18n.t(key, params);\r\n };\r\n\r\n useEffect(() => {\r\n document.documentElement.setAttribute('dir', isRTL ? 'rtl' : 'ltr');\r\n document.documentElement.setAttribute('lang', locale);\r\n }, [locale, isRTL]);\r\n\r\n return (\r\n <I18nContext.Provider value={{ locale, setLocale, t, isRTL }}>\r\n {children}\r\n </I18nContext.Provider>\r\n );\r\n}\r\n\r\n// Export useI18n hook here as well\r\nexport function useI18n() {\r\n const context = useContext(I18nContext);\r\n if (!context) {\r\n throw new Error('useI18n must be used within I18nProvider');\r\n }\r\n return context;\r\n}"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Locale = string;
|
|
2
|
+
type NestedTranslations = {
|
|
3
|
+
[key: string]: string | NestedTranslations;
|
|
4
|
+
};
|
|
5
|
+
type TranslationsRecord = Record<Locale, NestedTranslations>;
|
|
6
|
+
interface I18nConfig {
|
|
7
|
+
defaultLocale: Locale;
|
|
8
|
+
fallbackLocale?: Locale;
|
|
9
|
+
translations: TranslationsRecord;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type { I18nConfig as I, Locale as L, NestedTranslations as N, TranslationsRecord as T };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Locale = string;
|
|
2
|
+
type NestedTranslations = {
|
|
3
|
+
[key: string]: string | NestedTranslations;
|
|
4
|
+
};
|
|
5
|
+
type TranslationsRecord = Record<Locale, NestedTranslations>;
|
|
6
|
+
interface I18nConfig {
|
|
7
|
+
defaultLocale: Locale;
|
|
8
|
+
fallbackLocale?: Locale;
|
|
9
|
+
translations: TranslationsRecord;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type { I18nConfig as I, Locale as L, NestedTranslations as N, TranslationsRecord as T };
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "next-i18n-lite",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Lightweight i18n library for Next.js with TypeScript support",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"types": "./dist/react/index.d.ts",
|
|
16
|
+
"import": "./dist/react/index.mjs",
|
|
17
|
+
"require": "./dist/react/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"dev": "tsup --watch",
|
|
28
|
+
"prepublishOnly": "npm run build",
|
|
29
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"i18n",
|
|
33
|
+
"internationalization",
|
|
34
|
+
"nextjs",
|
|
35
|
+
"react",
|
|
36
|
+
"typescript",
|
|
37
|
+
"localization",
|
|
38
|
+
"translation"
|
|
39
|
+
],
|
|
40
|
+
"author": "codexpro410 <codexpro410@gmail.com>",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/codexpro410/next-i18n-lite.git"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/codexpro410/next-i18n-lite/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/codexpro410/next-i18n-lite#readme",
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"react": ">=18.0.0",
|
|
52
|
+
"react-dom": ">=18.0.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"react": {
|
|
56
|
+
"optional": false
|
|
57
|
+
},
|
|
58
|
+
"react-dom": {
|
|
59
|
+
"optional": false
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/node": "^20.0.0",
|
|
64
|
+
"@types/react": "^18.0.0",
|
|
65
|
+
"@types/react-dom": "^18.0.0",
|
|
66
|
+
"react": "^18.0.0",
|
|
67
|
+
"react-dom": "^18.0.0",
|
|
68
|
+
"tsup": "^8.0.0",
|
|
69
|
+
"typescript": "^5.0.0"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=18.0.0",
|
|
73
|
+
"npm": ">=9.0.0"
|
|
74
|
+
}
|
|
75
|
+
}
|