@digitaldefiance/i18n-lib 2.1.40 → 3.5.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.
Files changed (128) hide show
  1. package/README.md +405 -0
  2. package/package.json +1 -1
  3. package/src/core/component-store.d.ts +4 -0
  4. package/src/core/component-store.d.ts.map +1 -1
  5. package/src/core/component-store.js +27 -5
  6. package/src/core/component-store.js.map +1 -1
  7. package/src/errors/i18n-error.d.ts +6 -0
  8. package/src/errors/i18n-error.d.ts.map +1 -1
  9. package/src/errors/i18n-error.js +12 -0
  10. package/src/errors/i18n-error.js.map +1 -1
  11. package/src/gender/gender-categories.d.ts +7 -0
  12. package/src/gender/gender-categories.d.ts.map +1 -0
  13. package/src/gender/gender-categories.js +10 -0
  14. package/src/gender/gender-categories.js.map +1 -0
  15. package/src/gender/gender-resolver.d.ts +9 -0
  16. package/src/gender/gender-resolver.d.ts.map +1 -0
  17. package/src/gender/gender-resolver.js +30 -0
  18. package/src/gender/gender-resolver.js.map +1 -0
  19. package/src/gender/index.d.ts +3 -0
  20. package/src/gender/index.d.ts.map +1 -0
  21. package/src/gender/index.js +6 -0
  22. package/src/gender/index.js.map +1 -0
  23. package/src/icu/ast.d.ts +48 -0
  24. package/src/icu/ast.d.ts.map +1 -0
  25. package/src/icu/ast.js +16 -0
  26. package/src/icu/ast.js.map +1 -0
  27. package/src/icu/compiler.d.ts +16 -0
  28. package/src/icu/compiler.d.ts.map +1 -0
  29. package/src/icu/compiler.js +81 -0
  30. package/src/icu/compiler.js.map +1 -0
  31. package/src/icu/formatter-registry.d.ts +10 -0
  32. package/src/icu/formatter-registry.d.ts.map +1 -0
  33. package/src/icu/formatter-registry.js +34 -0
  34. package/src/icu/formatter-registry.js.map +1 -0
  35. package/src/icu/formatters/base-formatter.d.ts +8 -0
  36. package/src/icu/formatters/base-formatter.d.ts.map +1 -0
  37. package/src/icu/formatters/base-formatter.js +3 -0
  38. package/src/icu/formatters/base-formatter.js.map +1 -0
  39. package/src/icu/formatters/date-formatter.d.ts +5 -0
  40. package/src/icu/formatters/date-formatter.d.ts.map +1 -0
  41. package/src/icu/formatters/date-formatter.js +31 -0
  42. package/src/icu/formatters/date-formatter.js.map +1 -0
  43. package/src/icu/formatters/number-formatter.d.ts +5 -0
  44. package/src/icu/formatters/number-formatter.d.ts.map +1 -0
  45. package/src/icu/formatters/number-formatter.js +30 -0
  46. package/src/icu/formatters/number-formatter.js.map +1 -0
  47. package/src/icu/formatters/plural-formatter.d.ts +5 -0
  48. package/src/icu/formatters/plural-formatter.d.ts.map +1 -0
  49. package/src/icu/formatters/plural-formatter.js +15 -0
  50. package/src/icu/formatters/plural-formatter.js.map +1 -0
  51. package/src/icu/formatters/select-formatter.d.ts +5 -0
  52. package/src/icu/formatters/select-formatter.d.ts.map +1 -0
  53. package/src/icu/formatters/select-formatter.js +10 -0
  54. package/src/icu/formatters/select-formatter.js.map +1 -0
  55. package/src/icu/formatters/selectordinal-formatter.d.ts +5 -0
  56. package/src/icu/formatters/selectordinal-formatter.d.ts.map +1 -0
  57. package/src/icu/formatters/selectordinal-formatter.js +22 -0
  58. package/src/icu/formatters/selectordinal-formatter.js.map +1 -0
  59. package/src/icu/formatters/time-formatter.d.ts +5 -0
  60. package/src/icu/formatters/time-formatter.d.ts.map +1 -0
  61. package/src/icu/formatters/time-formatter.js +31 -0
  62. package/src/icu/formatters/time-formatter.js.map +1 -0
  63. package/src/icu/helpers.d.ts +9 -0
  64. package/src/icu/helpers.d.ts.map +1 -0
  65. package/src/icu/helpers.js +31 -0
  66. package/src/icu/helpers.js.map +1 -0
  67. package/src/icu/parser.d.ts +29 -0
  68. package/src/icu/parser.d.ts.map +1 -0
  69. package/src/icu/parser.js +194 -0
  70. package/src/icu/parser.js.map +1 -0
  71. package/src/icu/runtime.d.ts +10 -0
  72. package/src/icu/runtime.d.ts.map +1 -0
  73. package/src/icu/runtime.js +28 -0
  74. package/src/icu/runtime.js.map +1 -0
  75. package/src/icu/tokenizer.d.ts +37 -0
  76. package/src/icu/tokenizer.d.ts.map +1 -0
  77. package/src/icu/tokenizer.js +187 -0
  78. package/src/icu/tokenizer.js.map +1 -0
  79. package/src/icu/validator.d.ts +11 -0
  80. package/src/icu/validator.d.ts.map +1 -0
  81. package/src/icu/validator.js +140 -0
  82. package/src/icu/validator.js.map +1 -0
  83. package/src/index.d.ts +4 -0
  84. package/src/index.d.ts.map +1 -1
  85. package/src/index.js +4 -0
  86. package/src/index.js.map +1 -1
  87. package/src/interfaces/component-config.interface.d.ts +2 -1
  88. package/src/interfaces/component-config.interface.d.ts.map +1 -1
  89. package/src/pluralization/index.d.ts +7 -0
  90. package/src/pluralization/index.d.ts.map +1 -0
  91. package/src/pluralization/index.js +10 -0
  92. package/src/pluralization/index.js.map +1 -0
  93. package/src/pluralization/language-plural-map.d.ts +29 -0
  94. package/src/pluralization/language-plural-map.d.ts.map +1 -0
  95. package/src/pluralization/language-plural-map.js +136 -0
  96. package/src/pluralization/language-plural-map.js.map +1 -0
  97. package/src/pluralization/plural-categories.d.ts +22 -0
  98. package/src/pluralization/plural-categories.d.ts.map +1 -0
  99. package/src/pluralization/plural-categories.js +8 -0
  100. package/src/pluralization/plural-categories.js.map +1 -0
  101. package/src/pluralization/plural-rules.d.ts +102 -0
  102. package/src/pluralization/plural-rules.d.ts.map +1 -0
  103. package/src/pluralization/plural-rules.js +263 -0
  104. package/src/pluralization/plural-rules.js.map +1 -0
  105. package/src/types/index.d.ts +5 -0
  106. package/src/types/index.d.ts.map +1 -0
  107. package/src/types/index.js +8 -0
  108. package/src/types/index.js.map +1 -0
  109. package/src/types/plural-types.d.ts +17 -0
  110. package/src/types/plural-types.d.ts.map +1 -0
  111. package/src/types/plural-types.js +33 -0
  112. package/src/types/plural-types.js.map +1 -0
  113. package/src/utils/index.d.ts +1 -6
  114. package/src/utils/index.d.ts.map +1 -1
  115. package/src/utils/index.js +1 -6
  116. package/src/utils/index.js.map +1 -1
  117. package/src/utils/plural-helpers.d.ts +10 -0
  118. package/src/utils/plural-helpers.d.ts.map +1 -0
  119. package/src/utils/plural-helpers.js +19 -0
  120. package/src/utils/plural-helpers.js.map +1 -0
  121. package/src/validation/index.d.ts +2 -0
  122. package/src/validation/index.d.ts.map +1 -0
  123. package/src/validation/index.js +5 -0
  124. package/src/validation/index.js.map +1 -0
  125. package/src/validation/plural-validator.d.ts +23 -0
  126. package/src/validation/plural-validator.d.ts.map +1 -0
  127. package/src/validation/plural-validator.js +105 -0
  128. package/src/validation/plural-validator.js.map +1 -0
package/README.md CHANGED
@@ -6,7 +6,11 @@ Part of [Express Suite](https://github.com/Digital-Defiance/express-suite)
6
6
 
7
7
  ## Features
8
8
 
9
+ - **ICU MessageFormat**: Industry-standard message formatting with plural, select, date/time/number formatting
9
10
  - **Component-Based Architecture**: Register translation components with full type safety
11
+ - **37 Supported Languages**: CLDR-compliant plural rules for world's most complex languages
12
+ - **Pluralization Support**: Automatic plural form selection based on count (one/few/many/other)
13
+ - **Gender Support**: Gender-aware translations (male/female/neutral/other)
10
14
  - **8 Built-in Languages**: English (US/UK), French, Spanish, German, Chinese, Japanese, Ukrainian
11
15
  - **Advanced Template Processing**:
12
16
  - Component references: `{{Component.key}}`
@@ -69,6 +73,258 @@ console.log(engine.translate('app', 'welcome', { appName: 'MyApp' }));
69
73
  engine.setLanguage(LanguageCodes.FR);
70
74
  console.log(engine.translate('app', 'welcome', { appName: 'MyApp' }));
71
75
  // Output: "Bienvenue sur MyApp!"
76
+
77
+ // Pluralization (automatic form selection)
78
+ engine.register({
79
+ id: 'cart',
80
+ strings: {
81
+ 'en-US': {
82
+ items: {
83
+ one: '1 item',
84
+ other: '{count} items'
85
+ }
86
+ }
87
+ }
88
+ });
89
+
90
+ console.log(engine.translate('cart', 'items', { count: 1 }));
91
+ // Output: "1 item"
92
+ console.log(engine.translate('cart', 'items', { count: 5 }));
93
+ // Output: "5 items"
94
+ ```
95
+
96
+ ## ICU MessageFormat
97
+
98
+ Industry-standard message formatting with powerful features. See [@docs/ICU_MESSAGEFORMAT.md](../../docs/ICU_MESSAGEFORMAT.md) for complete guide.
99
+
100
+ ### Quick Example
101
+
102
+ ```typescript
103
+ import { formatICUMessage } from '@digitaldefiance/i18n-lib';
104
+
105
+ // Simple variable
106
+ formatICUMessage('Hello {name}', { name: 'Alice' });
107
+ // → "Hello Alice"
108
+
109
+ // Plural
110
+ formatICUMessage('{count, plural, one {# item} other {# items}}', { count: 1 });
111
+ // → "1 item"
112
+
113
+ // Select
114
+ formatICUMessage('{gender, select, male {He} female {She} other {They}}', { gender: 'male' });
115
+ // → "He"
116
+
117
+ // Number formatting
118
+ formatICUMessage('{price, number, currency}', { price: 99.99 }, 'en-US');
119
+ // → "$99.99"
120
+
121
+ // Complex nested
122
+ formatICUMessage(
123
+ '{gender, select, male {He has} female {She has}} {count, plural, one {# item} other {# items}}',
124
+ { gender: 'female', count: 2 }
125
+ );
126
+ // → "She has 2 items"
127
+ ```
128
+
129
+ ### Features
130
+
131
+ - ✅ **Full ICU Syntax**: Variables, plural, select, selectordinal
132
+ - ✅ **Formatters**: Number (integer, currency, percent), Date, Time
133
+ - ✅ **37 Languages**: CLDR plural rules for all supported languages
134
+ - ✅ **Nested Messages**: Up to 4 levels deep
135
+ - ✅ **Performance**: <1ms per format, message caching
136
+ - ✅ **Specification Compliant**: Unicode ICU, CLDR, FormatJS compatible
137
+
138
+ ### Documentation
139
+
140
+ - **[@docs/ICU_MESSAGEFORMAT.md](../../docs/ICU_MESSAGEFORMAT.md)** - Complete guide with syntax reference and examples
141
+ - **[@docs/ICU_COMPREHENSIVE_VALIDATION.md](../../docs/ICU_COMPREHENSIVE_VALIDATION.md)** - Validation report with test coverage
142
+ - **[@docs/ICU_PROJECT_COMPLETE.md](../../docs/ICU_PROJECT_COMPLETE.md)** - Implementation summary
143
+
144
+ ### API
145
+
146
+ ```typescript
147
+ import {
148
+ formatICUMessage, // One-line formatting
149
+ isICUMessage, // Detect ICU format
150
+ parseICUMessage, // Parse to AST
151
+ compileICUMessage, // Compile to function
152
+ validateICUMessage, // Validate syntax
153
+ Runtime // Advanced usage
154
+ } from '@digitaldefiance/i18n-lib';
155
+ ```
156
+
157
+ ---
158
+
159
+ ## Pluralization & Gender
160
+
161
+ ### Pluralization
162
+
163
+ Automatic plural form selection based on count with CLDR-compliant rules for 37 languages:
164
+
165
+ ```typescript
166
+ import { createPluralString } from '@digitaldefiance/i18n-lib';
167
+
168
+ // English (one/other)
169
+ engine.register({
170
+ id: 'shop',
171
+ strings: {
172
+ 'en-US': {
173
+ items: createPluralString({
174
+ one: '{count} item',
175
+ other: '{count} items'
176
+ })
177
+ }
178
+ }
179
+ });
180
+
181
+ // Russian (one/few/many)
182
+ engine.register({
183
+ id: 'shop',
184
+ strings: {
185
+ 'ru': {
186
+ items: createPluralString({
187
+ one: '{count} товар',
188
+ few: '{count} товара',
189
+ many: '{count} товаров'
190
+ })
191
+ }
192
+ }
193
+ });
194
+
195
+ // Arabic (zero/one/two/few/many/other)
196
+ engine.register({
197
+ id: 'shop',
198
+ strings: {
199
+ 'ar': {
200
+ items: createPluralString({
201
+ zero: 'لا عناصر',
202
+ one: 'عنصر واحد',
203
+ two: 'عنصران',
204
+ few: '{count} عناصر',
205
+ many: '{count} عنصرًا',
206
+ other: '{count} عنصر'
207
+ })
208
+ }
209
+ }
210
+ });
211
+
212
+ // Automatic form selection
213
+ engine.translate('shop', 'items', { count: 1 }); // "1 item"
214
+ engine.translate('shop', 'items', { count: 5 }); // "5 items"
215
+ engine.translate('shop', 'items', { count: 21 }, 'ru'); // "21 товар"
216
+ ```
217
+
218
+ **Supported Languages** (37 total):
219
+ - **Simple** (other only): Japanese, Chinese, Korean, Turkish, Vietnamese, Thai, Indonesian, Malay
220
+ - **Two forms** (one/other): English, German, Spanish, Italian, Portuguese, Dutch, Swedish, Norwegian, Danish, Finnish, Greek, Hebrew, Hindi
221
+ - **Three forms** (one/few/many): Russian, Ukrainian, Romanian, Latvian
222
+ - **Four forms**: Polish, Czech, Lithuanian, Slovenian, Scottish Gaelic
223
+ - **Five forms**: Irish, Breton
224
+ - **Six forms**: Arabic, Welsh
225
+
226
+ See [PLURALIZATION_SUPPORT.md](docs/PLURALIZATION_SUPPORT.md) for complete language matrix.
227
+
228
+ ### Gender Support
229
+
230
+ Gender-aware translations with intelligent fallback:
231
+
232
+ ```typescript
233
+ import { createGenderedString } from '@digitaldefiance/i18n-lib';
234
+
235
+ engine.register({
236
+ id: 'profile',
237
+ strings: {
238
+ 'en-US': {
239
+ greeting: createGenderedString({
240
+ male: 'Welcome, Mr. {name}',
241
+ female: 'Welcome, Ms. {name}',
242
+ neutral: 'Welcome, {name}'
243
+ })
244
+ }
245
+ }
246
+ });
247
+
248
+ engine.translate('profile', 'greeting', { name: 'Smith', gender: 'male' });
249
+ // Output: "Welcome, Mr. Smith"
250
+ ```
251
+
252
+ ### Combined Plural + Gender
253
+
254
+ Nested plural and gender forms:
255
+
256
+ ```typescript
257
+ // Plural → Gender
258
+ const pluralGender = {
259
+ one: {
260
+ male: 'He has {count} item',
261
+ female: 'She has {count} item'
262
+ },
263
+ other: {
264
+ male: 'He has {count} items',
265
+ female: 'She has {count} items'
266
+ }
267
+ };
268
+
269
+ // Gender → Plural
270
+ const genderPlural = {
271
+ male: {
272
+ one: 'He has {count} item',
273
+ other: 'He has {count} items'
274
+ },
275
+ female: {
276
+ one: 'She has {count} item',
277
+ other: 'She has {count} items'
278
+ }
279
+ };
280
+ ```
281
+
282
+ ### Helper Functions
283
+
284
+ ```typescript
285
+ import {
286
+ createPluralString,
287
+ createGenderedString,
288
+ getRequiredPluralForms
289
+ } from '@digitaldefiance/i18n-lib';
290
+
291
+ // Get required forms for a language
292
+ const forms = getRequiredPluralForms('ru');
293
+ // Returns: ['one', 'few', 'many']
294
+
295
+ // Type-safe plural string creation
296
+ const plural = createPluralString({
297
+ one: '1 item',
298
+ other: '{count} items'
299
+ });
300
+
301
+ // Type-safe gender string creation
302
+ const gender = createGenderedString({
303
+ male: 'He',
304
+ female: 'She',
305
+ neutral: 'They'
306
+ });
307
+ ```
308
+
309
+ ### Validation
310
+
311
+ ```typescript
312
+ import { validatePluralForms } from '@digitaldefiance/i18n-lib';
313
+
314
+ // Validate plural forms for a language
315
+ const result = validatePluralForms(
316
+ { one: 'item', other: 'items' },
317
+ 'en',
318
+ 'items',
319
+ { strict: true, checkUnused: true, checkVariables: true }
320
+ );
321
+
322
+ if (!result.isValid) {
323
+ console.error('Errors:', result.errors);
324
+ }
325
+ if (result.warnings.length > 0) {
326
+ console.warn('Warnings:', result.warnings);
327
+ }
72
328
  ```
73
329
 
74
330
  ## Core Concepts
@@ -502,6 +758,155 @@ Contributions welcome! Please:
502
758
 
503
759
  ## ChangeLog
504
760
 
761
+ ### Version 3.5.0
762
+
763
+ **Major Feature Release** - ICU MessageFormat Support
764
+
765
+ **New Features:**
766
+
767
+ - **ICU MessageFormat**: Full industry-standard message formatting
768
+ - Parser with 6 AST node types (MESSAGE, LITERAL, ARGUMENT, PLURAL, SELECT, SELECTORDINAL)
769
+ - Tokenizer with sophisticated depth tracking
770
+ - Semantic validator with configurable options
771
+ - Message compiler (AST → executable function)
772
+ - Runtime with message caching
773
+ - 304 tests passing (100%)
774
+
775
+ - **Formatters**: 6 built-in formatters
776
+ - NumberFormatter (integer, currency, percent)
777
+ - DateFormatter (short, medium, long, full)
778
+ - TimeFormatter (short, medium, long, full)
779
+ - PluralFormatter (37 languages via CLDR)
780
+ - SelectFormatter
781
+ - SelectOrdinalFormatter
782
+ - FormatterRegistry (pluggable system)
783
+
784
+ - **Helper Functions**: Easy-to-use utilities
785
+ - `formatICUMessage()` - One-line formatting
786
+ - `isICUMessage()` - Detect ICU format
787
+ - `parseICUMessage()` - Parse to AST
788
+ - `compileICUMessage()` - Compile to function
789
+ - `validateICUMessage()` - Validate syntax
790
+
791
+ - **Advanced Features**:
792
+ - Nested messages (4 levels tested)
793
+ - Missing value handling
794
+ - Performance optimization (<1ms/format)
795
+ - Memory-efficient caching
796
+ - Multilingual validation (12 languages, 6 writing systems)
797
+
798
+ **Documentation:**
799
+
800
+ - [ICU_MESSAGEFORMAT.md](docs/ICU_MESSAGEFORMAT.md) - Complete guide
801
+ - [ICU_COMPREHENSIVE_VALIDATION.md](docs/ICU_COMPREHENSIVE_VALIDATION.md) - Validation report
802
+ - [ICU_PROJECT_COMPLETE.md](docs/ICU_PROJECT_COMPLETE.md) - Implementation summary
803
+
804
+ **Testing:**
805
+
806
+ - 304 ICU tests passing (100%)
807
+ - Specification compliance (Unicode ICU, CLDR)
808
+ - Industry compatibility (React Intl, Vue I18n, Angular)
809
+ - Edge case coverage (nesting, Unicode, RTL, special chars)
810
+ - Performance validation (<1ms, 1000 formats in <100ms)
811
+
812
+ **Migration:**
813
+
814
+ ```typescript
815
+ // Use ICU MessageFormat
816
+ import { formatICUMessage } from '@digitaldefiance/i18n-lib';
817
+
818
+ formatICUMessage('Hello {name}', { name: 'Alice' });
819
+ formatICUMessage('{count, plural, one {# item} other {# items}}', { count: 1 });
820
+ ```
821
+
822
+ ### Version 3.0.0
823
+
824
+ **Major Feature Release** - Pluralization & Gender Support
825
+
826
+ **New Features:**
827
+
828
+ - **CLDR Pluralization**: Full support for 37 languages with automatic plural form selection
829
+ - 19 unique plural rule implementations (English, Russian, Arabic, Polish, French, Spanish, Japanese, Ukrainian, Chinese, German, Scottish Gaelic, Welsh, Breton, Slovenian, Czech, Lithuanian, Latvian, Irish, Romanian)
830
+ - 18 additional languages reusing existing rules
831
+ - Handles world's most complex plural systems (Arabic 6 forms, Welsh 6 forms, Breton 5 forms)
832
+ - Intelligent fallback: requested form → 'other' → first available
833
+ - Type-safe `PluralString` type with backward compatibility
834
+
835
+ - **Gender Support**: Gender-aware translations with 4 categories
836
+ - Gender categories: male, female, neutral, other
837
+ - `GenderedString` type for type-safe gender forms
838
+ - Intelligent fallback: requested → neutral → other → first available
839
+ - Works seamlessly with pluralization
840
+
841
+ - **Combined Plural + Gender**: Nested plural and gender resolution
842
+ - Supports both plural→gender and gender→plural nesting
843
+ - Full fallback support for missing forms
844
+ - Works with all 37 supported languages
845
+
846
+ - **Validation System**: Comprehensive plural form validation
847
+ - `validatePluralForms()` - Validates required forms per language
848
+ - `validateCountVariable()` - Ensures count variable exists
849
+ - Strict and lenient modes
850
+ - Variable consistency checking
851
+ - Unused form detection
852
+
853
+ - **Helper Functions**: Utilities for easy plural/gender string creation
854
+ - `createPluralString()` - Type-safe plural object creation
855
+ - `createGenderedString()` - Type-safe gender object creation
856
+ - `getRequiredPluralForms()` - Get required forms for any language
857
+
858
+ - **Error Handling**: New error codes for pluralization
859
+ - `PLURAL_FORM_NOT_FOUND` - Missing plural form with suggestions
860
+ - `INVALID_PLURAL_CATEGORY` - Invalid category with valid options
861
+ - `MISSING_COUNT_VARIABLE` - Count variable missing when plurals used
862
+
863
+ **Documentation:**
864
+
865
+ - [PLURALIZATION_SUPPORT.md](docs/PLURALIZATION_SUPPORT.md) - Complete language support matrix
866
+ - [PLURALIZATION_USAGE.md](docs/PLURALIZATION_USAGE.md) - Usage guide with examples
867
+ - [ADDING_LANGUAGES.md](docs/ADDING_LANGUAGES.md) - Guide for adding custom languages
868
+ - Updated README with pluralization and gender sections
869
+
870
+ **Testing:**
871
+
872
+ - 348 tests passing (92% of roadmap target)
873
+ - 100% coverage on pluralization, gender, and validation code
874
+ - Comprehensive edge case testing
875
+ - Integration tests for complex scenarios
876
+
877
+ **Migration:**
878
+
879
+ ```typescript
880
+ // Simple strings continue to work unchanged
881
+ engine.register({
882
+ id: 'app',
883
+ strings: {
884
+ 'en-US': {
885
+ title: 'My App' // Still works
886
+ }
887
+ }
888
+ });
889
+
890
+ // Add pluralization
891
+ import { createPluralString } from '@digitaldefiance/i18n-lib';
892
+
893
+ engine.register({
894
+ id: 'cart',
895
+ strings: {
896
+ 'en-US': {
897
+ items: createPluralString({
898
+ one: '{count} item',
899
+ other: '{count} items'
900
+ })
901
+ }
902
+ }
903
+ });
904
+
905
+ // Use with count variable
906
+ engine.translate('cart', 'items', { count: 5 });
907
+ // Output: "5 items"
908
+ ```
909
+
505
910
  ### Version 2.1.40
506
911
 
507
912
  - Alignment
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitaldefiance/i18n-lib",
3
- "version": "2.1.40",
3
+ "version": "3.5.0",
4
4
  "description": "i18n library with enum translation support",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -13,6 +13,10 @@ export declare class ComponentStore {
13
13
  get(componentId: string): ComponentConfig;
14
14
  getAll(): readonly ComponentConfig[];
15
15
  translate(componentId: string, key: string, variables?: Record<string, any>, language?: string): string;
16
+ /**
17
+ * Resolve plural form from a PluralString based on count variable
18
+ */
19
+ private resolvePluralForm;
16
20
  safeTranslate(componentId: string, key: string, variables?: Record<string, any>, language?: string): string;
17
21
  private validate;
18
22
  setConstants(constants: Record<string, any>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"component-store.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/core/component-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGlE,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAsB;gBAE5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI3C,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,gBAAgB;IAkBnD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,gBAAgB;IAe9F,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;IASzC,MAAM,IAAI,SAAS,eAAe,EAAE;IAIpC,SAAS,CACP,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM;IAgBT,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM;IAQT,OAAO,CAAC,QAAQ;IA2BhB,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAIlD,KAAK,IAAI,IAAI;CAId"}
1
+ {"version":3,"file":"component-store.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/core/component-store.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAKlE,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAsC;IACxD,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,SAAS,CAAC,CAAsB;gBAE5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAI3C,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,gBAAgB;IAkBnD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,gBAAgB;IAe9F,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAIjC,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe;IASzC,MAAM,IAAI,SAAS,eAAe,EAAE;IAIpC,SAAS,CACP,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM;IAoBT;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsBzB,aAAa,CACX,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM;IAQT,OAAO,CAAC,QAAQ;IA2BhB,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAIlD,KAAK,IAAI,IAAI;CAId"}
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ComponentStore = void 0;
7
7
  const errors_1 = require("../errors");
8
8
  const utils_1 = require("../utils");
9
+ const plural_types_1 = require("../types/plural-types");
10
+ const language_plural_map_1 = require("../pluralization/language-plural-map");
9
11
  class ComponentStore {
10
12
  components = new Map();
11
13
  aliasMap = new Map();
@@ -55,16 +57,36 @@ class ComponentStore {
55
57
  }
56
58
  translate(componentId, key, variables, language) {
57
59
  const component = this.get(componentId);
58
- const langStrings = component.strings[language || 'en-US'];
60
+ const lang = language || 'en-US';
61
+ const langStrings = component.strings[lang];
59
62
  if (!langStrings) {
60
- throw errors_1.I18nError.languageNotFound(language || 'en-US');
63
+ throw errors_1.I18nError.languageNotFound(lang);
61
64
  }
62
- const translation = langStrings[key];
63
- if (!translation) {
64
- throw errors_1.I18nError.translationMissing(componentId, key, language || 'en-US');
65
+ const value = langStrings[key];
66
+ if (!value) {
67
+ throw errors_1.I18nError.translationMissing(componentId, key, lang);
65
68
  }
69
+ // Resolve plural form if needed
70
+ const translation = this.resolvePluralForm(value, variables?.count, lang);
66
71
  return (0, utils_1.replaceVariables)(translation, variables, this.constants);
67
72
  }
73
+ /**
74
+ * Resolve plural form from a PluralString based on count variable
75
+ */
76
+ resolvePluralForm(value, count, language) {
77
+ // If it's a simple string, return as-is
78
+ if (typeof value === 'string') {
79
+ return value;
80
+ }
81
+ // If no count provided, use 'other' form or first available
82
+ if (count === undefined) {
83
+ return (0, plural_types_1.resolvePluralString)(value, 'other') || '';
84
+ }
85
+ // Get the appropriate plural category for this count and language
86
+ const category = (0, language_plural_map_1.getPluralCategory)(language, count);
87
+ // Resolve the plural form with fallback logic
88
+ return (0, plural_types_1.resolvePluralString)(value, category) || '';
89
+ }
68
90
  safeTranslate(componentId, key, variables, language) {
69
91
  try {
70
92
  return this.translate(componentId, key, variables, language);
@@ -1 +1 @@
1
- {"version":3,"file":"component-store.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/core/component-store.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,sCAAsC;AAEtC,oCAA4C;AAE5C,MAAa,cAAc;IACjB,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;IAChD,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,SAAS,CAAuB;IAExC,YAAY,SAA+B;QACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,MAAuB;QAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACnC,MAAM,kBAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAEvC,mBAAmB;QACnB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,OAA+C;QACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,kBAAS,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,OAAO,GAAoB;YAC/B,GAAG,QAAQ;YACX,OAAO,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE;SAC7C,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,kBAAS,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,SAAS,CACP,WAAmB,EACnB,GAAW,EACX,SAA+B,EAC/B,QAAiB;QAEjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;QAE3D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,kBAAS,CAAC,gBAAgB,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,kBAAS,CAAC,kBAAkB,CAAC,WAAW,EAAE,GAAG,EAAE,QAAQ,IAAI,OAAO,CAAC,CAAC;QAC5E,CAAC;QAED,OAAO,IAAA,wBAAgB,EAAC,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;IAED,aAAa,CACX,WAAmB,EACnB,GAAW,EACX,SAA+B,EAC/B,QAAiB;QAEjB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,WAAW,IAAI,GAAG,GAAG,CAAC;QACnC,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,MAAuB;QACtC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,uCAAuC;QACvC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACjE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,QAAQ,CAAC,IAAI,CAAC,gBAAgB,GAAG,mBAAmB,IAAI,mBAAmB,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC3F,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;YAC5B,MAAM;YACN,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,SAA8B;QACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF;AAhID,wCAgIC"}
1
+ {"version":3,"file":"component-store.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/core/component-store.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,sCAAsC;AAEtC,oCAA4C;AAC5C,wDAA0F;AAC1F,8EAAyE;AAEzE,MAAa,cAAc;IACjB,UAAU,GAAG,IAAI,GAAG,EAA2B,CAAC;IAChD,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC;IACrC,SAAS,CAAuB;IAExC,YAAY,SAA+B;QACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,QAAQ,CAAC,MAAuB;QAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;YACnC,MAAM,kBAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAEvC,mBAAmB;QACnB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,OAA+C;QACzE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,kBAAS,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QAED,MAAM,OAAO,GAAoB;YAC/B,GAAG,QAAQ;YACX,OAAO,EAAE,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE;SAC7C,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC5E,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC;QACzD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,kBAAS,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,SAAS,CACP,WAAmB,EACnB,GAAW,EACX,SAA+B,EAC/B,QAAiB;QAEjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,QAAQ,IAAI,OAAO,CAAC;QACjC,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,kBAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,kBAAS,CAAC,kBAAkB,CAAC,WAAW,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7D,CAAC;QAED,gCAAgC;QAChC,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAE1E,OAAO,IAAA,wBAAgB,EAAC,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACK,iBAAiB,CACvB,KAA4B,EAC5B,KAAyB,EACzB,QAAgB;QAEhB,wCAAwC;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4DAA4D;QAC5D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,IAAA,kCAAmB,EAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;QACnD,CAAC;QAED,kEAAkE;QAClE,MAAM,QAAQ,GAAG,IAAA,uCAAiB,EAAC,QAAQ,EAAE,KAAK,CAAQ,CAAC;QAE3D,8CAA8C;QAC9C,OAAO,IAAA,kCAAmB,EAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IACpD,CAAC;IAED,aAAa,CACX,WAAmB,EACnB,GAAW,EACX,SAA+B,EAC/B,QAAiB;QAEjB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC/D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,WAAW,IAAI,GAAG,GAAG,CAAC;QACnC,CAAC;IACH,CAAC;IAEO,QAAQ,CAAC,MAAuB;QACtC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,uCAAuC;QACvC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACjE,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,QAAQ,CAAC,IAAI,CAAC,gBAAgB,GAAG,mBAAmB,IAAI,mBAAmB,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;gBAC3F,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;YAC5B,MAAM;YACN,QAAQ;SACT,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,SAA8B;QACzC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACF;AA7JD,wCA6JC"}
@@ -13,6 +13,9 @@ export declare const I18nErrorCode: {
13
13
  readonly INSTANCE_NOT_FOUND: "INSTANCE_NOT_FOUND";
14
14
  readonly INSTANCE_EXISTS: "INSTANCE_EXISTS";
15
15
  readonly INVALID_CONTEXT: "INVALID_CONTEXT";
16
+ readonly PLURAL_FORM_NOT_FOUND: "PLURAL_FORM_NOT_FOUND";
17
+ readonly INVALID_PLURAL_CATEGORY: "INVALID_PLURAL_CATEGORY";
18
+ readonly MISSING_COUNT_VARIABLE: "MISSING_COUNT_VARIABLE";
16
19
  };
17
20
  export type I18nErrorCode = (typeof I18nErrorCode)[keyof typeof I18nErrorCode];
18
21
  export declare class I18nError extends Error {
@@ -30,5 +33,8 @@ export declare class I18nError extends Error {
30
33
  static instanceNotFound(key: string): I18nError;
31
34
  static instanceExists(key: string): I18nError;
32
35
  static invalidContext(contextKey: string): I18nError;
36
+ static pluralFormNotFound(category: string, language: string, key: string, availableForms: string[]): I18nError;
37
+ static invalidPluralCategory(category: string, validCategories: string[]): I18nError;
38
+ static missingCountVariable(key: string): I18nError;
33
39
  }
34
40
  //# sourceMappingURL=i18n-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"i18n-error.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/errors/i18n-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;CAYhB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE/E,qBAAa,SAAU,SAAQ,KAAK;aAEhB,IAAI,EAAE,aAAa;aAEnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;gBAF9B,IAAI,EAAE,aAAa,EACnC,OAAO,EAAE,MAAM,EACC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,YAAA;IAOhD,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAQxD,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;IAQ3E,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAQpD,MAAM,CAAC,kBAAkB,CACvB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,SAAS;IAQZ,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAI/C,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAQzD,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAQrD,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS;IAQpD,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAQ/C,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAQ7C,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;CAOrD"}
1
+ {"version":3,"file":"i18n-error.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/errors/i18n-error.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;CAehB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE/E,qBAAa,SAAU,SAAQ,KAAK;aAEhB,IAAI,EAAE,aAAa;aAEnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;gBAF9B,IAAI,EAAE,aAAa,EACnC,OAAO,EAAE,MAAM,EACC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,YAAA;IAOhD,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAQxD,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;IAQ3E,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAQpD,MAAM,CAAC,kBAAkB,CACvB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,SAAS;IAQZ,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAI/C,MAAM,CAAC,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS;IAQzD,MAAM,CAAC,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IAQrD,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS;IAQpD,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAQ/C,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAQ7C,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;IAQpD,MAAM,CAAC,kBAAkB,CACvB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,EAAE,GACvB,SAAS;IAQZ,MAAM,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS;IAQpF,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;CAOpD"}
@@ -16,6 +16,9 @@ exports.I18nErrorCode = {
16
16
  INSTANCE_NOT_FOUND: 'INSTANCE_NOT_FOUND',
17
17
  INSTANCE_EXISTS: 'INSTANCE_EXISTS',
18
18
  INVALID_CONTEXT: 'INVALID_CONTEXT',
19
+ PLURAL_FORM_NOT_FOUND: 'PLURAL_FORM_NOT_FOUND',
20
+ INVALID_PLURAL_CATEGORY: 'INVALID_PLURAL_CATEGORY',
21
+ MISSING_COUNT_VARIABLE: 'MISSING_COUNT_VARIABLE',
19
22
  };
20
23
  class I18nError extends Error {
21
24
  code;
@@ -60,6 +63,15 @@ class I18nError extends Error {
60
63
  static invalidContext(contextKey) {
61
64
  return new I18nError(exports.I18nErrorCode.INVALID_CONTEXT, `Invalid context key '${contextKey}'`, { contextKey });
62
65
  }
66
+ static pluralFormNotFound(category, language, key, availableForms) {
67
+ return new I18nError(exports.I18nErrorCode.PLURAL_FORM_NOT_FOUND, `Plural form '${category}' not found for language '${language}' in key '${key}'. Available forms: ${availableForms.join(', ')}`, { category, language, key, availableForms });
68
+ }
69
+ static invalidPluralCategory(category, validCategories) {
70
+ return new I18nError(exports.I18nErrorCode.INVALID_PLURAL_CATEGORY, `Invalid plural category '${category}'. Valid categories: ${validCategories.join(', ')}`, { category, validCategories });
71
+ }
72
+ static missingCountVariable(key) {
73
+ return new I18nError(exports.I18nErrorCode.MISSING_COUNT_VARIABLE, `Plural forms used in key '${key}' but no 'count' variable provided`, { key });
74
+ }
63
75
  }
64
76
  exports.I18nError = I18nError;
65
77
  //# sourceMappingURL=i18n-error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"i18n-error.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/errors/i18n-error.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"i18n-error.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/errors/i18n-error.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Gender categories for gendered translations
3
+ */
4
+ export type GenderCategory = 'male' | 'female' | 'neutral' | 'other';
5
+ export type GenderedString = string | Partial<Record<GenderCategory, string>>;
6
+ export declare function isGenderedString(value: any): value is Partial<Record<GenderCategory, string>>;
7
+ //# sourceMappingURL=gender-categories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gender-categories.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/gender/gender-categories.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAErE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AAE9E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAE7F"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * Gender categories for gendered translations
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isGenderedString = isGenderedString;
7
+ function isGenderedString(value) {
8
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
9
+ }
10
+ //# sourceMappingURL=gender-categories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gender-categories.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/gender/gender-categories.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAMH,4CAEC;AAFD,SAAgB,gBAAgB,CAAC,KAAU;IACzC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Gender form resolution
3
+ */
4
+ import { GenderCategory, GenderedString } from './gender-categories';
5
+ /**
6
+ * Resolve gender form with fallback logic
7
+ */
8
+ export declare function resolveGenderForm(value: GenderedString, gender: GenderCategory | string | undefined): string;
9
+ //# sourceMappingURL=gender-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gender-resolver.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-i18n-lib/src/gender/gender-resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAoB,MAAM,qBAAqB,CAAC;AAEvF;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,GAC1C,MAAM,CAsBR"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * Gender form resolution
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolveGenderForm = resolveGenderForm;
7
+ const gender_categories_1 = require("./gender-categories");
8
+ /**
9
+ * Resolve gender form with fallback logic
10
+ */
11
+ function resolveGenderForm(value, gender) {
12
+ if (typeof value === 'string') {
13
+ return value;
14
+ }
15
+ if (!(0, gender_categories_1.isGenderedString)(value)) {
16
+ return '';
17
+ }
18
+ // No gender provided - use neutral or other or first available
19
+ if (!gender) {
20
+ return value.neutral || value.other || Object.values(value)[0] || '';
21
+ }
22
+ // Try requested gender
23
+ const requested = value[gender];
24
+ if (requested) {
25
+ return requested;
26
+ }
27
+ // Fallback: neutral → other → first available
28
+ return value.neutral || value.other || Object.values(value)[0] || '';
29
+ }
30
+ //# sourceMappingURL=gender-resolver.js.map