@maz-ui/translations 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LouisMazel
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,262 @@
1
+ # @maz-ui/translations
2
+
3
+ Simple and lightweight translation system for Maz-UI components.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @maz-ui/translations
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - 🌍 **Simple internationalization** for Maz-UI components
14
+ - 🔄 **Reactive locale switching**
15
+ - 📝 **Variable interpolation** in translations
16
+ - 🎯 **TypeScript support** with full type safety
17
+ - 🔧 **Plugin-based** integration with Vue applications
18
+ - 📦 **Lightweight** - minimal bundle size impact
19
+ - 🎨 **Customizable** - override default translations easily
20
+
21
+ ## Usage
22
+
23
+ ### Basic Configuration
24
+
25
+ ```typescript
26
+ import { MazTranslationsPlugin } from '@maz-ui/translations'
27
+ import { createApp } from 'vue'
28
+
29
+ const app = createApp(App)
30
+
31
+ app.use(MazTranslationsPlugin, {
32
+ locale: 'fr',
33
+ translations: {
34
+ fr: {
35
+ select: { noOptions: 'Aucune option disponible' },
36
+ input: { required: 'Ce champ est requis' }
37
+ },
38
+ es: {
39
+ select: { noOptions: 'No hay opciones disponibles' },
40
+ input: { required: 'Este campo es obligatorio' }
41
+ }
42
+ }
43
+ })
44
+ ```
45
+
46
+ ### In Vue Components
47
+
48
+ ```vue
49
+ <script setup>
50
+ import { useTranslations } from '@maz-ui/translations'
51
+
52
+ const { t, locale, setLocale } = useTranslations()
53
+
54
+ // Basic usage
55
+ const message = t('select.noOptions')
56
+
57
+ // With variables
58
+ const welcomeMessage = t('input.welcome', { name: 'John' })
59
+
60
+ // Change language
61
+ function switchLanguage(lang) {
62
+ setLocale(lang)
63
+ }
64
+ </script>
65
+
66
+ <template>
67
+ <div>
68
+ <p>{{ t('select.noOptions') }}</p>
69
+ <p>{{ t('input.welcome', { name: 'User' }) }}</p>
70
+
71
+ <div class="language-switcher">
72
+ <button @click="setLocale('en')">
73
+ English
74
+ </button>
75
+ <button @click="setLocale('fr')">
76
+ Français
77
+ </button>
78
+ <button @click="setLocale('es')">
79
+ Español
80
+ </button>
81
+ </div>
82
+
83
+ <p>Current locale: {{ locale }}</p>
84
+ </div>
85
+ </template>
86
+ ```
87
+
88
+ ### Variable Interpolation
89
+
90
+ The translation system supports variable interpolation using curly braces:
91
+
92
+ ```typescript
93
+ // Configuration
94
+ const translations = {
95
+ en: {
96
+ welcome: 'Hello {name}!',
97
+ itemCount: 'You have {count} {count, plural, one {item} other {items}}'
98
+ }
99
+ }
100
+
101
+ // Usage
102
+ t('welcome', { name: 'John' }) // "Hello John!"
103
+ t('itemCount', { count: 1 }) // "You have 1 item"
104
+ t('itemCount', { count: 5 }) // "You have 5 items"
105
+ ```
106
+
107
+ ### Advanced Usage
108
+
109
+ #### Manual Instance Creation
110
+
111
+ ```typescript
112
+ import { createMazTranslations } from '@maz-ui/translations'
113
+
114
+ const i18n = createMazTranslations({
115
+ locale: 'en',
116
+ translations: {
117
+ en: { /* your translations */ },
118
+ fr: { /* your translations */ }
119
+ }
120
+ })
121
+
122
+ // Use directly
123
+ const message = i18n.t('select.noOptions')
124
+ ```
125
+
126
+ #### Custom Translation Keys
127
+
128
+ ```typescript
129
+ // Define your own translation structure
130
+ const customTranslations = {
131
+ en: {
132
+ navigation: {
133
+ home: 'Home',
134
+ about: 'About',
135
+ contact: 'Contact'
136
+ },
137
+ form: {
138
+ validation: {
139
+ required: 'This field is required',
140
+ email: 'Please enter a valid email'
141
+ }
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ ## API Reference
148
+
149
+ ### `useTranslations()`
150
+
151
+ Returns an object with:
152
+
153
+ - **`t(key, variables?)`** - Translation function
154
+ - `key`: Translation key (dot notation supported)
155
+ - `variables`: Optional object with variable substitutions
156
+ - Returns: Translated string or key if not found
157
+
158
+ - **`locale`** - Current locale (reactive ref)
159
+ - Type: `Ref<string>`
160
+ - Reactive property that updates when locale changes
161
+
162
+ - **`setLocale(locale)`** - Change current locale
163
+ - `locale`: New locale string
164
+ - Triggers reactivity for all components using translations
165
+
166
+ ### Plugin Options
167
+
168
+ ```typescript
169
+ interface MazTranslationsOptions {
170
+ locale?: string // Default locale (default: 'en')
171
+ translations?: Record<string, Partial<MazTranslations>> // Custom translations
172
+ }
173
+ ```
174
+
175
+ ### Type Definitions
176
+
177
+ ```typescript
178
+ interface MazTranslationsInstance {
179
+ locale: Ref<string>
180
+ t: (key: string, variables?: Record<string, any>) => string
181
+ setLocale: (locale: string) => void
182
+ }
183
+
184
+ interface MazTranslations {
185
+ select: { noOptions: string }
186
+ input: { required: string }
187
+ datePicker: { placeholder: string }
188
+ // ... other component translations
189
+ }
190
+ ```
191
+
192
+ ## Default Translations
193
+
194
+ The package includes default English translations for Maz-UI components. You can override any of these by providing your own translations.
195
+
196
+ ### Default Structure
197
+
198
+ ```typescript
199
+ const defaultTranslations = {
200
+ select: {
201
+ noOptions: 'No options available'
202
+ },
203
+ input: {
204
+ required: 'This field is required'
205
+ },
206
+ datePicker: {
207
+ placeholder: 'Select date...'
208
+ }
209
+ }
210
+ ```
211
+
212
+ ### Adding New Languages
213
+
214
+ ```typescript
215
+ app.use(MazTranslationsPlugin, {
216
+ locale: 'fr',
217
+ translations: {
218
+ fr: {
219
+ select: { noOptions: 'Aucune option disponible' },
220
+ input: { required: 'Ce champ est requis' },
221
+ datePicker: { placeholder: 'Sélectionner une date...' }
222
+ },
223
+ de: {
224
+ select: { noOptions: 'Keine Optionen verfügbar' },
225
+ input: { required: 'Dieses Feld ist erforderlich' },
226
+ datePicker: { placeholder: 'Datum auswählen...' }
227
+ }
228
+ }
229
+ })
230
+ ```
231
+
232
+ ### Handle Pluralization
233
+
234
+ ```typescript
235
+ // Simple approach
236
+ const simpleTranslations = {
237
+ en: {
238
+ itemCount: '{count} item(s)'
239
+ }
240
+ }
241
+
242
+ // Better approach
243
+ const betterTranslations = {
244
+ en: {
245
+ itemCountSingular: '{count} item',
246
+ itemCountPlural: '{count} items'
247
+ }
248
+ }
249
+ ```
250
+
251
+ ## Contributing
252
+
253
+ Contributions are welcome! Please ensure:
254
+
255
+ - New translations follow the existing key structure
256
+ - TypeScript types are properly updated
257
+ - Tests are added for new features
258
+ - Documentation is updated accordingly
259
+
260
+ ## License
261
+
262
+ MIT License - see LICENSE file for details.
@@ -0,0 +1,81 @@
1
+ const de = {
2
+ selectCountry: {
3
+ searchPlaceholder: "Land suchen"
4
+ },
5
+ inputPhoneNumber: {
6
+ countrySelect: {
7
+ placeholder: "L\xE4ndercode",
8
+ error: "Land w\xE4hlen",
9
+ searchPlaceholder: "Land suchen"
10
+ },
11
+ phoneInput: {
12
+ placeholder: "Telefonnummer",
13
+ example: "Beispiel: {example}"
14
+ }
15
+ },
16
+ dropzone: {
17
+ dragAndDrop: "Dateien ablegen",
18
+ selectFile: "Datei ausw\xE4hlen",
19
+ divider: "oder",
20
+ fileMaxCount: "Maximal {count} Dateien",
21
+ fileMaxSize: "Maximal {size} MB",
22
+ fileTypes: "Erlaubte Dateitypen: {types}"
23
+ },
24
+ datePicker: {
25
+ shortcuts: {
26
+ lastSevenDays: "Letzte 7 Tage",
27
+ lastThirtyDays: "Letzte 30 Tage",
28
+ thisWeek: "Diese Woche",
29
+ lastWeek: "Letzte Woche",
30
+ thisMonth: "Dieser Monat",
31
+ thisYear: "Dieses Jahr",
32
+ lastYear: "Letztes Jahr"
33
+ }
34
+ },
35
+ dropdown: {
36
+ screenReaderDescription: "Dropdown-Men\xFC \xF6ffnen"
37
+ },
38
+ select: {
39
+ searchPlaceholder: "Suchen"
40
+ },
41
+ table: {
42
+ noResults: "Keine Ergebnisse",
43
+ actionColumnTitle: "Aktionen",
44
+ searchByInput: {
45
+ all: "Alle",
46
+ placeholder: "Suchen nach"
47
+ },
48
+ searchInput: {
49
+ placeholder: "Suchen"
50
+ },
51
+ pagination: {
52
+ all: "Alle",
53
+ rowsPerPage: "Zeilen pro Seite",
54
+ of: "von"
55
+ }
56
+ },
57
+ pagination: {
58
+ navAriaLabel: "Seitennavigation",
59
+ screenReader: {
60
+ firstPage: "Erste Seite, Seite {page}",
61
+ previousPage: "Vorherige Seite, Seite {page}",
62
+ page: "Seite {page}",
63
+ nextPage: "N\xE4chste Seite, Seite {page}",
64
+ lastPage: "Letzte Seite, Seite {page}"
65
+ }
66
+ },
67
+ carousel: {
68
+ ariaLabel: {
69
+ previousButton: "Zu vorherigen Elementen scrollen",
70
+ nextButton: "Zu n\xE4chsten Elementen scrollen"
71
+ }
72
+ },
73
+ checklist: {
74
+ noResultsFound: "Keine Ergebnisse gefunden",
75
+ searchInput: {
76
+ placeholder: "Suchen"
77
+ }
78
+ }
79
+ };
80
+
81
+ export { de as default };
@@ -0,0 +1,144 @@
1
+ const en = {
2
+ /**
3
+ * This is the translation for the input phone number component.
4
+ * The keys are:
5
+ * - countrySelect: The translation for the country select.
6
+ * - phoneInput: The translation for the phone input.
7
+ */
8
+ selectCountry: {
9
+ searchPlaceholder: "Search country"
10
+ },
11
+ inputPhoneNumber: {
12
+ /**
13
+ * This is the translation for the country select component.
14
+ * The keys are:
15
+ * - placeholder: The translation for the placeholder text.
16
+ * - error: The translation for the error text.
17
+ * - searchPlaceholder: The translation for the search placeholder text.
18
+ */
19
+ countrySelect: {
20
+ placeholder: "Country code",
21
+ error: "Choose country",
22
+ searchPlaceholder: "Search the country"
23
+ },
24
+ /**
25
+ * This is the translation for the phone input component.
26
+ * The keys are:
27
+ * - placeholder: The translation for the placeholder text.
28
+ * - example: The translation for the example text.
29
+ */
30
+ phoneInput: {
31
+ placeholder: "Phone number",
32
+ example: "Example: {example}"
33
+ }
34
+ },
35
+ /**
36
+ * This is the translation for the dropzone component.
37
+ * The keys are:
38
+ * - dragAndDrop: The translation for the drag and drop text.
39
+ * - selectFile: The translation for the select file button.
40
+ * - divider: The translation for the divider text.
41
+ * - fileMaxCount: The translation for the maximum number of files.
42
+ * - fileMaxSize: The translation for the maximum size of the files.
43
+ * - fileTypes: The translation for the allowed file types.
44
+ */
45
+ dropzone: {
46
+ dragAndDrop: "Drop your files",
47
+ selectFile: "Select file",
48
+ divider: "or",
49
+ fileMaxCount: "Maximum {count} files",
50
+ fileMaxSize: "Maximum {size} MB",
51
+ fileTypes: "Allowed file types: {types}"
52
+ },
53
+ /**
54
+ * This is the translation for the date picker component.
55
+ * The keys are:
56
+ * - shortcuts: The translation for the shortcuts.
57
+ */
58
+ datePicker: {
59
+ shortcuts: {
60
+ lastSevenDays: "Last 7 days",
61
+ lastThirtyDays: "Last 30 days",
62
+ thisWeek: "This week",
63
+ lastWeek: "Last week",
64
+ thisMonth: "This month",
65
+ thisYear: "This year",
66
+ lastYear: "Last year"
67
+ }
68
+ },
69
+ /**
70
+ * This is the translation for the dropdown component.
71
+ * The keys are:
72
+ * - screenReaderDescription: The translation for the screen reader description.
73
+ */
74
+ dropdown: {
75
+ screenReaderDescription: "Open menu dropdown"
76
+ },
77
+ /**
78
+ * This is the translation for the select component.
79
+ * The keys are:
80
+ * - searchPlaceholder: The translation for the search placeholder text.
81
+ */
82
+ select: {
83
+ searchPlaceholder: "Search"
84
+ },
85
+ /**
86
+ * This is the translation for the table component.
87
+ * The keys are:
88
+ * - noResults: The translation for the no results text.
89
+ * - actionColumnTitle: The translation for the action column title.
90
+ * - searchByInput: The translation for the search by input.
91
+ * - searchInput: The translation for the search input.
92
+ * - pagination: The translation for the pagination component.
93
+ */
94
+ table: {
95
+ noResults: "No results",
96
+ actionColumnTitle: "Actions",
97
+ searchByInput: {
98
+ all: "All",
99
+ placeholder: "Search by"
100
+ },
101
+ searchInput: {
102
+ placeholder: "Search"
103
+ },
104
+ pagination: {
105
+ all: "All",
106
+ rowsPerPage: "Rows per page",
107
+ of: "of"
108
+ }
109
+ },
110
+ /**
111
+ * This is the translation for the pagination component.
112
+ * The keys are:
113
+ * - navAriaLabel: The aria-label for the navigation (nav) element.
114
+ * - screenReader.firstPage: The translation for the first page button (screen reader).
115
+ * - screenReader.previousPage: The translation for the previous page button (screen reader).
116
+ * - screenReader.page: The translation for the current page button (screen reader).
117
+ * - screenReader.nextPage: The translation for the next page button (screen reader).
118
+ * - screenReader.lastPage: The translation for the last page button (screen reader).
119
+ */
120
+ pagination: {
121
+ navAriaLabel: "page navigation",
122
+ screenReader: {
123
+ firstPage: "First Page, page {page}",
124
+ previousPage: "Previous Page, page {page}",
125
+ page: "Page {page}",
126
+ nextPage: "Next Page, page {page}",
127
+ lastPage: "Last Page, page {page}"
128
+ }
129
+ },
130
+ carousel: {
131
+ ariaLabel: {
132
+ previousButton: "Scroll to previous items",
133
+ nextButton: "Scroll to next items"
134
+ }
135
+ },
136
+ checklist: {
137
+ noResultsFound: "No results found",
138
+ searchInput: {
139
+ placeholder: "Search"
140
+ }
141
+ }
142
+ };
143
+
144
+ export { en as default };
@@ -0,0 +1,81 @@
1
+ const es = {
2
+ selectCountry: {
3
+ searchPlaceholder: "Buscar pa\xEDs"
4
+ },
5
+ inputPhoneNumber: {
6
+ countrySelect: {
7
+ placeholder: "C\xF3digo de pa\xEDs",
8
+ error: "Elegir pa\xEDs",
9
+ searchPlaceholder: "Buscar pa\xEDs"
10
+ },
11
+ phoneInput: {
12
+ placeholder: "N\xFAmero de tel\xE9fono",
13
+ example: "Ejemplo: {example}"
14
+ }
15
+ },
16
+ dropzone: {
17
+ dragAndDrop: "Arrastra tus archivos",
18
+ selectFile: "Seleccionar archivo",
19
+ divider: "o",
20
+ fileMaxCount: "M\xE1ximo {count} archivos",
21
+ fileMaxSize: "M\xE1ximo {size} MB",
22
+ fileTypes: "Tipos de archivo permitidos: {types}"
23
+ },
24
+ datePicker: {
25
+ shortcuts: {
26
+ lastSevenDays: "\xDAltimos 7 d\xEDas",
27
+ lastThirtyDays: "\xDAltimos 30 d\xEDas",
28
+ thisWeek: "Esta semana",
29
+ lastWeek: "Semana pasada",
30
+ thisMonth: "Este mes",
31
+ thisYear: "Este a\xF1o",
32
+ lastYear: "A\xF1o pasado"
33
+ }
34
+ },
35
+ dropdown: {
36
+ screenReaderDescription: "Abrir men\xFA desplegable"
37
+ },
38
+ select: {
39
+ searchPlaceholder: "Buscar"
40
+ },
41
+ table: {
42
+ noResults: "Sin resultados",
43
+ actionColumnTitle: "Acciones",
44
+ searchByInput: {
45
+ all: "Todos",
46
+ placeholder: "Buscar por"
47
+ },
48
+ searchInput: {
49
+ placeholder: "Buscar"
50
+ },
51
+ pagination: {
52
+ all: "Todos",
53
+ rowsPerPage: "Filas por p\xE1gina",
54
+ of: "de"
55
+ }
56
+ },
57
+ pagination: {
58
+ navAriaLabel: "navegaci\xF3n de p\xE1ginas",
59
+ screenReader: {
60
+ firstPage: "Primera p\xE1gina, p\xE1gina {page}",
61
+ previousPage: "P\xE1gina anterior, p\xE1gina {page}",
62
+ page: "P\xE1gina {page}",
63
+ nextPage: "P\xE1gina siguiente, p\xE1gina {page}",
64
+ lastPage: "\xDAltima p\xE1gina, p\xE1gina {page}"
65
+ }
66
+ },
67
+ carousel: {
68
+ ariaLabel: {
69
+ previousButton: "Desplazar a elementos anteriores",
70
+ nextButton: "Desplazar a elementos siguientes"
71
+ }
72
+ },
73
+ checklist: {
74
+ noResultsFound: "No se encontraron resultados",
75
+ searchInput: {
76
+ placeholder: "Buscar"
77
+ }
78
+ }
79
+ };
80
+
81
+ export { es as default };
@@ -0,0 +1,81 @@
1
+ const fr = {
2
+ selectCountry: {
3
+ searchPlaceholder: "Rechercher un pays"
4
+ },
5
+ inputPhoneNumber: {
6
+ countrySelect: {
7
+ placeholder: "Code pays",
8
+ error: "Choisir le pays",
9
+ searchPlaceholder: "Rechercher un pays"
10
+ },
11
+ phoneInput: {
12
+ placeholder: "Num\xE9ro de t\xE9l\xE9phone",
13
+ example: "Exemple: {example}"
14
+ }
15
+ },
16
+ dropzone: {
17
+ dragAndDrop: "D\xE9poser vos fichiers",
18
+ selectFile: "S\xE9lectionner un fichier",
19
+ divider: "ou",
20
+ fileMaxCount: "Maximum {count} fichiers",
21
+ fileMaxSize: "Maximum {size} MB",
22
+ fileTypes: "Types de fichiers autoris\xE9s: {types}"
23
+ },
24
+ datePicker: {
25
+ shortcuts: {
26
+ lastSevenDays: "Derniers 7 jours",
27
+ lastThirtyDays: "Derniers 30 jours",
28
+ thisWeek: "Cette semaine",
29
+ lastWeek: "Semaine pr\xE9c\xE9dente",
30
+ thisMonth: "Ce mois",
31
+ thisYear: "Cette ann\xE9e",
32
+ lastYear: "Ann\xE9e pr\xE9c\xE9dente"
33
+ }
34
+ },
35
+ checklist: {
36
+ noResultsFound: "Aucun r\xE9sultat trouv\xE9",
37
+ searchInput: {
38
+ placeholder: "Rechercher..."
39
+ }
40
+ },
41
+ carousel: {
42
+ ariaLabel: {
43
+ previousButton: "Scroller vers la gauche",
44
+ nextButton: "Scroller vers la droite"
45
+ }
46
+ },
47
+ dropdown: {
48
+ screenReaderDescription: "Ouvrir le menu d\xE9roulant"
49
+ },
50
+ select: {
51
+ searchPlaceholder: "Rechercher"
52
+ },
53
+ pagination: {
54
+ navAriaLabel: "Navigation",
55
+ screenReader: {
56
+ firstPage: "Premi\xE8re page",
57
+ previousPage: "Page pr\xE9c\xE9dente",
58
+ page: "Page {page}",
59
+ nextPage: "Page suivante",
60
+ lastPage: "Derni\xE8re page"
61
+ }
62
+ },
63
+ table: {
64
+ actionColumnTitle: "Actions",
65
+ noResults: "Aucun r\xE9sultat",
66
+ searchByInput: {
67
+ all: "Tous",
68
+ placeholder: "Rechercher par"
69
+ },
70
+ searchInput: {
71
+ placeholder: "Rechercher"
72
+ },
73
+ pagination: {
74
+ all: "Tous",
75
+ rowsPerPage: "Lignes par page",
76
+ of: "sur"
77
+ }
78
+ }
79
+ };
80
+
81
+ export { fr as default };