@digitaldefiance/i18n-lib 3.7.5 → 3.8.1
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 +261 -0
- package/package.json +12 -4
- package/src/active-context.ts +4 -0
- package/src/builders/i18n-builder.ts +82 -0
- package/src/builders/{index.d.ts → index.ts} +1 -1
- package/src/component-definition.ts +11 -0
- package/src/component-registration.ts +29 -0
- package/src/component-registry.ts +432 -0
- package/src/context-error-type.ts +7 -0
- package/src/core/component-store.ts +241 -0
- package/src/core/context-manager.ts +113 -0
- package/src/core/enum-registry.ts +106 -0
- package/src/core/i18n-engine.ts +710 -0
- package/src/core/index.ts +16 -0
- package/src/core/language-registry.ts +345 -0
- package/src/core-component-id.ts +5 -0
- package/src/core-i18n.ts +270 -0
- package/src/core-plugin-factory.ts +111 -0
- package/src/core-string-key.ts +59 -0
- package/src/create-translation-adapter.ts +93 -0
- package/src/enum-registry.ts +152 -0
- package/src/errors/base.ts +8 -0
- package/src/errors/context-error.ts +122 -0
- package/src/errors/enhanced-error-base.ts +260 -0
- package/src/errors/handleable.ts +152 -0
- package/src/errors/i18n-error.ts +494 -0
- package/src/errors/index.ts +15 -0
- package/src/errors/simple-typed-error.ts +81 -0
- package/src/errors/{index.d.ts → translatable-exports.ts} +3 -5
- package/src/errors/translatable-generic.ts +245 -0
- package/src/errors/translatable-handleable-generic.ts +222 -0
- package/src/errors/translatable.ts +138 -0
- package/src/errors/typed-handleable.ts +138 -0
- package/src/errors/typed.ts +617 -0
- package/src/gender/{gender-categories.d.ts → gender-categories.ts} +6 -2
- package/src/gender/gender-resolver.ts +40 -0
- package/src/gender/{index.d.ts → index.ts} +0 -1
- package/src/global-active-context.ts +266 -0
- package/src/icu/ast.ts +56 -0
- package/src/icu/compiler.ts +96 -0
- package/src/icu/formatter-registry.ts +36 -0
- package/src/icu/formatters/base-formatter.ts +8 -0
- package/src/icu/formatters/date-formatter.ts +30 -0
- package/src/icu/formatters/number-formatter.ts +32 -0
- package/src/icu/formatters/plural-formatter.ts +12 -0
- package/src/icu/formatters/select-formatter.ts +7 -0
- package/src/icu/formatters/selectordinal-formatter.ts +17 -0
- package/src/icu/formatters/time-formatter.ts +30 -0
- package/src/icu/helpers.ts +34 -0
- package/src/icu/parser.ts +242 -0
- package/src/icu/runtime.ts +37 -0
- package/src/icu/tokenizer.ts +212 -0
- package/src/icu/validator.ts +163 -0
- package/src/{index.d.ts → index.ts} +46 -14
- package/src/interfaces/active-context.interface.ts +41 -0
- package/src/interfaces/component-config.interface.ts +17 -0
- package/src/interfaces/engine-config.interface.ts +22 -0
- package/src/interfaces/global-active-context.ts +39 -0
- package/src/interfaces/handleable-error-options.ts +13 -0
- package/src/interfaces/handleable.ts +20 -0
- package/src/interfaces/i18n-engine.interface.ts +57 -0
- package/src/interfaces/index.ts +13 -0
- package/src/interfaces/language-definition.interface.ts +17 -0
- package/src/interfaces/translation-options.interface.ts +15 -0
- package/src/interfaces/validation-result.interface.ts +24 -0
- package/src/language-codes.ts +40 -0
- package/src/language-definition.ts +13 -0
- package/src/plugin-i18n-engine.ts +707 -0
- package/src/pluralization/{index.d.ts → index.ts} +1 -1
- package/src/pluralization/language-plural-map.ts +186 -0
- package/src/pluralization/{plural-categories.d.ts → plural-categories.ts} +5 -3
- package/src/pluralization/plural-rules.ts +228 -0
- package/src/registry-config.ts +16 -0
- package/src/registry-error-type.ts +19 -0
- package/src/registry-error.ts +100 -0
- package/src/strict-types.ts +35 -0
- package/src/strings/de.ts +75 -0
- package/src/strings/en-GB.ts +74 -0
- package/src/strings/en-US.ts +74 -0
- package/src/strings/es.ts +74 -0
- package/src/strings/fr.ts +75 -0
- package/src/strings/ja.ts +73 -0
- package/src/strings/uk.ts +73 -0
- package/src/strings/zh-CN.ts +72 -0
- package/src/template.ts +72 -0
- package/src/translation-engine.ts +18 -0
- package/src/translation-request.ts +12 -0
- package/src/translation-response.ts +8 -0
- package/src/types/engine.ts +55 -0
- package/src/types/{index.d.ts → index.ts} +1 -1
- package/src/types/{plural-types.d.ts → plural-types.ts} +29 -3
- package/src/types.ts +142 -0
- package/src/utils/currency.ts +141 -0
- package/src/utils/html-escape.ts +55 -0
- package/src/utils/{index.d.ts → index.ts} +0 -1
- package/src/utils/lru-cache.ts +76 -0
- package/src/utils/{plural-helpers.d.ts → plural-helpers.ts} +14 -4
- package/src/utils/{safe-object.js → safe-object.ts} +37 -34
- package/src/utils/string-utils.ts +77 -0
- package/src/utils/timezone.ts +76 -0
- package/src/utils/validation.ts +66 -0
- package/src/utils.ts +215 -0
- package/src/validation/{index.d.ts → index.ts} +0 -1
- package/src/validation/plural-validator.ts +168 -0
- package/src/validation-config.ts +11 -0
- package/src/validation-result.ts +12 -0
- package/src/active-context.d.ts +0 -36
- package/src/active-context.d.ts.map +0 -1
- package/src/active-context.js +0 -3
- package/src/active-context.js.map +0 -1
- package/src/builders/i18n-builder.d.ts +0 -26
- package/src/builders/i18n-builder.d.ts.map +0 -1
- package/src/builders/i18n-builder.js +0 -70
- package/src/builders/i18n-builder.js.map +0 -1
- package/src/builders/index.d.ts.map +0 -1
- package/src/builders/index.js +0 -8
- package/src/builders/index.js.map +0 -1
- package/src/component-definition.d.ts +0 -12
- package/src/component-definition.d.ts.map +0 -1
- package/src/component-definition.js +0 -3
- package/src/component-definition.js.map +0 -1
- package/src/component-registration.d.ts +0 -13
- package/src/component-registration.d.ts.map +0 -1
- package/src/component-registration.js +0 -3
- package/src/component-registration.js.map +0 -1
- package/src/component-registry.d.ts +0 -102
- package/src/component-registry.d.ts.map +0 -1
- package/src/component-registry.js +0 -282
- package/src/component-registry.js.map +0 -1
- package/src/context-error-type.d.ts +0 -8
- package/src/context-error-type.d.ts.map +0 -1
- package/src/context-error-type.js +0 -12
- package/src/context-error-type.js.map +0 -1
- package/src/core/component-store.d.ts +0 -93
- package/src/core/component-store.d.ts.map +0 -1
- package/src/core/component-store.js +0 -198
- package/src/core/component-store.js.map +0 -1
- package/src/core/context-manager.d.ts +0 -72
- package/src/core/context-manager.d.ts.map +0 -1
- package/src/core/context-manager.js +0 -98
- package/src/core/context-manager.js.map +0 -1
- package/src/core/enum-registry.d.ts +0 -48
- package/src/core/enum-registry.d.ts.map +0 -1
- package/src/core/enum-registry.js +0 -85
- package/src/core/enum-registry.js.map +0 -1
- package/src/core/i18n-engine.d.ts +0 -241
- package/src/core/i18n-engine.d.ts.map +0 -1
- package/src/core/i18n-engine.js +0 -568
- package/src/core/i18n-engine.js.map +0 -1
- package/src/core/index.d.ts +0 -9
- package/src/core/index.d.ts.map +0 -1
- package/src/core/index.js +0 -12
- package/src/core/index.js.map +0 -1
- package/src/core/language-registry.d.ts +0 -180
- package/src/core/language-registry.d.ts.map +0 -1
- package/src/core/language-registry.js +0 -295
- package/src/core/language-registry.js.map +0 -1
- package/src/core-i18n.d.ts +0 -91
- package/src/core-i18n.d.ts.map +0 -1
- package/src/core-i18n.js +0 -287
- package/src/core-i18n.js.map +0 -1
- package/src/core-string-key.d.ts +0 -52
- package/src/core-string-key.d.ts.map +0 -1
- package/src/core-string-key.js +0 -61
- package/src/core-string-key.js.map +0 -1
- package/src/create-translation-adapter.d.ts +0 -33
- package/src/create-translation-adapter.d.ts.map +0 -1
- package/src/create-translation-adapter.js +0 -72
- package/src/create-translation-adapter.js.map +0 -1
- package/src/enum-registry.d.ts +0 -65
- package/src/enum-registry.d.ts.map +0 -1
- package/src/enum-registry.js +0 -123
- package/src/enum-registry.js.map +0 -1
- package/src/errors/context-error.d.ts +0 -50
- package/src/errors/context-error.d.ts.map +0 -1
- package/src/errors/context-error.js +0 -75
- package/src/errors/context-error.js.map +0 -1
- package/src/errors/enhanced-error-base.d.ts +0 -125
- package/src/errors/enhanced-error-base.d.ts.map +0 -1
- package/src/errors/enhanced-error-base.js +0 -165
- package/src/errors/enhanced-error-base.js.map +0 -1
- package/src/errors/handleable.d.ts +0 -83
- package/src/errors/handleable.d.ts.map +0 -1
- package/src/errors/handleable.js +0 -136
- package/src/errors/handleable.js.map +0 -1
- package/src/errors/i18n-error.d.ts +0 -211
- package/src/errors/i18n-error.d.ts.map +0 -1
- package/src/errors/i18n-error.js +0 -358
- package/src/errors/i18n-error.js.map +0 -1
- package/src/errors/index.d.ts.map +0 -1
- package/src/errors/index.js +0 -17
- package/src/errors/index.js.map +0 -1
- package/src/errors/simple-typed-error.d.ts +0 -53
- package/src/errors/simple-typed-error.d.ts.map +0 -1
- package/src/errors/simple-typed-error.js +0 -51
- package/src/errors/simple-typed-error.js.map +0 -1
- package/src/errors/translatable-generic.d.ts +0 -84
- package/src/errors/translatable-generic.d.ts.map +0 -1
- package/src/errors/translatable-generic.js +0 -134
- package/src/errors/translatable-generic.js.map +0 -1
- package/src/errors/translatable-handleable-generic.d.ts +0 -116
- package/src/errors/translatable-handleable-generic.d.ts.map +0 -1
- package/src/errors/translatable-handleable-generic.js +0 -121
- package/src/errors/translatable-handleable-generic.js.map +0 -1
- package/src/errors/translatable.d.ts +0 -59
- package/src/errors/translatable.d.ts.map +0 -1
- package/src/errors/translatable.js +0 -80
- package/src/errors/translatable.js.map +0 -1
- package/src/errors/typed-handleable.d.ts +0 -62
- package/src/errors/typed-handleable.d.ts.map +0 -1
- package/src/errors/typed-handleable.js +0 -106
- package/src/errors/typed-handleable.js.map +0 -1
- package/src/errors/typed.d.ts +0 -206
- package/src/errors/typed.d.ts.map +0 -1
- package/src/errors/typed.js +0 -452
- package/src/errors/typed.js.map +0 -1
- package/src/gender/gender-categories.d.ts.map +0 -1
- package/src/gender/gender-categories.js +0 -15
- package/src/gender/gender-categories.js.map +0 -1
- package/src/gender/gender-resolver.d.ts +0 -14
- package/src/gender/gender-resolver.d.ts.map +0 -1
- package/src/gender/gender-resolver.js +0 -35
- package/src/gender/gender-resolver.js.map +0 -1
- package/src/gender/index.d.ts.map +0 -1
- package/src/gender/index.js +0 -6
- package/src/gender/index.js.map +0 -1
- package/src/global-active-context.d.ts +0 -50
- package/src/global-active-context.d.ts.map +0 -1
- package/src/global-active-context.js +0 -185
- package/src/global-active-context.js.map +0 -1
- package/src/icu/ast.d.ts +0 -48
- package/src/icu/ast.d.ts.map +0 -1
- package/src/icu/ast.js +0 -16
- package/src/icu/ast.js.map +0 -1
- package/src/icu/compiler.d.ts +0 -16
- package/src/icu/compiler.d.ts.map +0 -1
- package/src/icu/compiler.js +0 -87
- package/src/icu/compiler.js.map +0 -1
- package/src/icu/formatter-registry.d.ts +0 -10
- package/src/icu/formatter-registry.d.ts.map +0 -1
- package/src/icu/formatter-registry.js +0 -34
- package/src/icu/formatter-registry.js.map +0 -1
- package/src/icu/formatters/base-formatter.d.ts +0 -8
- package/src/icu/formatters/base-formatter.d.ts.map +0 -1
- package/src/icu/formatters/base-formatter.js +0 -3
- package/src/icu/formatters/base-formatter.js.map +0 -1
- package/src/icu/formatters/date-formatter.d.ts +0 -5
- package/src/icu/formatters/date-formatter.d.ts.map +0 -1
- package/src/icu/formatters/date-formatter.js +0 -31
- package/src/icu/formatters/date-formatter.js.map +0 -1
- package/src/icu/formatters/number-formatter.d.ts +0 -5
- package/src/icu/formatters/number-formatter.d.ts.map +0 -1
- package/src/icu/formatters/number-formatter.js +0 -33
- package/src/icu/formatters/number-formatter.js.map +0 -1
- package/src/icu/formatters/plural-formatter.d.ts +0 -5
- package/src/icu/formatters/plural-formatter.d.ts.map +0 -1
- package/src/icu/formatters/plural-formatter.js +0 -15
- package/src/icu/formatters/plural-formatter.js.map +0 -1
- package/src/icu/formatters/select-formatter.d.ts +0 -5
- package/src/icu/formatters/select-formatter.d.ts.map +0 -1
- package/src/icu/formatters/select-formatter.js +0 -10
- package/src/icu/formatters/select-formatter.js.map +0 -1
- package/src/icu/formatters/selectordinal-formatter.d.ts +0 -5
- package/src/icu/formatters/selectordinal-formatter.d.ts.map +0 -1
- package/src/icu/formatters/selectordinal-formatter.js +0 -22
- package/src/icu/formatters/selectordinal-formatter.js.map +0 -1
- package/src/icu/formatters/time-formatter.d.ts +0 -5
- package/src/icu/formatters/time-formatter.d.ts.map +0 -1
- package/src/icu/formatters/time-formatter.js +0 -31
- package/src/icu/formatters/time-formatter.js.map +0 -1
- package/src/icu/helpers.d.ts +0 -9
- package/src/icu/helpers.d.ts.map +0 -1
- package/src/icu/helpers.js +0 -31
- package/src/icu/helpers.js.map +0 -1
- package/src/icu/parser.d.ts +0 -31
- package/src/icu/parser.d.ts.map +0 -1
- package/src/icu/parser.js +0 -203
- package/src/icu/parser.js.map +0 -1
- package/src/icu/runtime.d.ts +0 -10
- package/src/icu/runtime.d.ts.map +0 -1
- package/src/icu/runtime.js +0 -33
- package/src/icu/runtime.js.map +0 -1
- package/src/icu/tokenizer.d.ts +0 -37
- package/src/icu/tokenizer.d.ts.map +0 -1
- package/src/icu/tokenizer.js +0 -187
- package/src/icu/tokenizer.js.map +0 -1
- package/src/icu/validator.d.ts +0 -11
- package/src/icu/validator.d.ts.map +0 -1
- package/src/icu/validator.js +0 -140
- package/src/icu/validator.js.map +0 -1
- package/src/index.d.ts.map +0 -1
- package/src/index.js +0 -76
- package/src/index.js.map +0 -1
- package/src/interfaces/component-config.interface.d.ts +0 -16
- package/src/interfaces/component-config.interface.d.ts.map +0 -1
- package/src/interfaces/component-config.interface.js +0 -6
- package/src/interfaces/component-config.interface.js.map +0 -1
- package/src/interfaces/engine-config.interface.d.ts +0 -22
- package/src/interfaces/engine-config.interface.d.ts.map +0 -1
- package/src/interfaces/engine-config.interface.js +0 -6
- package/src/interfaces/engine-config.interface.js.map +0 -1
- package/src/interfaces/global-active-context.d.ts +0 -23
- package/src/interfaces/global-active-context.d.ts.map +0 -1
- package/src/interfaces/global-active-context.js +0 -3
- package/src/interfaces/global-active-context.js.map +0 -1
- package/src/interfaces/handleable-error-options.d.ts +0 -14
- package/src/interfaces/handleable-error-options.d.ts.map +0 -1
- package/src/interfaces/handleable-error-options.js +0 -3
- package/src/interfaces/handleable-error-options.js.map +0 -1
- package/src/interfaces/handleable.d.ts +0 -21
- package/src/interfaces/handleable.d.ts.map +0 -1
- package/src/interfaces/handleable.js +0 -3
- package/src/interfaces/handleable.js.map +0 -1
- package/src/interfaces/i18n-engine.interface.d.ts +0 -46
- package/src/interfaces/i18n-engine.interface.d.ts.map +0 -1
- package/src/interfaces/i18n-engine.interface.js +0 -6
- package/src/interfaces/i18n-engine.interface.js.map +0 -1
- package/src/interfaces/index.d.ts +0 -11
- package/src/interfaces/index.d.ts.map +0 -1
- package/src/interfaces/index.js +0 -14
- package/src/interfaces/index.js.map +0 -1
- package/src/interfaces/language-definition.interface.d.ts +0 -17
- package/src/interfaces/language-definition.interface.d.ts.map +0 -1
- package/src/interfaces/language-definition.interface.js +0 -6
- package/src/interfaces/language-definition.interface.js.map +0 -1
- package/src/interfaces/translation-options.interface.d.ts +0 -15
- package/src/interfaces/translation-options.interface.d.ts.map +0 -1
- package/src/interfaces/translation-options.interface.js +0 -6
- package/src/interfaces/translation-options.interface.js.map +0 -1
- package/src/interfaces/validation-result.interface.d.ts +0 -24
- package/src/interfaces/validation-result.interface.d.ts.map +0 -1
- package/src/interfaces/validation-result.interface.js +0 -6
- package/src/interfaces/validation-result.interface.js.map +0 -1
- package/src/language-codes.d.ts +0 -28
- package/src/language-codes.d.ts.map +0 -1
- package/src/language-codes.js +0 -32
- package/src/language-codes.js.map +0 -1
- package/src/language-definition.d.ts +0 -14
- package/src/language-definition.d.ts.map +0 -1
- package/src/language-definition.js +0 -3
- package/src/language-definition.js.map +0 -1
- package/src/plugin-i18n-engine.d.ts +0 -164
- package/src/plugin-i18n-engine.d.ts.map +0 -1
- package/src/plugin-i18n-engine.js +0 -489
- package/src/plugin-i18n-engine.js.map +0 -1
- package/src/pluralization/index.d.ts.map +0 -1
- package/src/pluralization/index.js +0 -10
- package/src/pluralization/index.js.map +0 -1
- package/src/pluralization/language-plural-map.d.ts +0 -29
- package/src/pluralization/language-plural-map.d.ts.map +0 -1
- package/src/pluralization/language-plural-map.js +0 -155
- package/src/pluralization/language-plural-map.js.map +0 -1
- package/src/pluralization/plural-categories.d.ts.map +0 -1
- package/src/pluralization/plural-categories.js +0 -8
- package/src/pluralization/plural-categories.js.map +0 -1
- package/src/pluralization/plural-rules.d.ts +0 -102
- package/src/pluralization/plural-rules.d.ts.map +0 -1
- package/src/pluralization/plural-rules.js +0 -263
- package/src/pluralization/plural-rules.js.map +0 -1
- package/src/registry-config.d.ts +0 -16
- package/src/registry-config.d.ts.map +0 -1
- package/src/registry-config.js +0 -3
- package/src/registry-config.js.map +0 -1
- package/src/registry-error-type.d.ts +0 -20
- package/src/registry-error-type.d.ts.map +0 -1
- package/src/registry-error-type.js +0 -24
- package/src/registry-error-type.js.map +0 -1
- package/src/registry-error.d.ts +0 -19
- package/src/registry-error.d.ts.map +0 -1
- package/src/registry-error.js +0 -49
- package/src/registry-error.js.map +0 -1
- package/src/strict-types.d.ts +0 -19
- package/src/strict-types.d.ts.map +0 -1
- package/src/strict-types.js +0 -18
- package/src/strict-types.js.map +0 -1
- package/src/strings/de.d.ts +0 -3
- package/src/strings/de.d.ts.map +0 -1
- package/src/strings/de.js +0 -57
- package/src/strings/de.js.map +0 -1
- package/src/strings/en-GB.d.ts +0 -3
- package/src/strings/en-GB.d.ts.map +0 -1
- package/src/strings/en-GB.js +0 -57
- package/src/strings/en-GB.js.map +0 -1
- package/src/strings/en-US.d.ts +0 -3
- package/src/strings/en-US.d.ts.map +0 -1
- package/src/strings/en-US.js +0 -57
- package/src/strings/en-US.js.map +0 -1
- package/src/strings/es.d.ts +0 -3
- package/src/strings/es.d.ts.map +0 -1
- package/src/strings/es.js +0 -57
- package/src/strings/es.js.map +0 -1
- package/src/strings/fr.d.ts +0 -3
- package/src/strings/fr.d.ts.map +0 -1
- package/src/strings/fr.js +0 -57
- package/src/strings/fr.js.map +0 -1
- package/src/strings/ja.d.ts +0 -3
- package/src/strings/ja.d.ts.map +0 -1
- package/src/strings/ja.js +0 -57
- package/src/strings/ja.js.map +0 -1
- package/src/strings/uk.d.ts +0 -3
- package/src/strings/uk.d.ts.map +0 -1
- package/src/strings/uk.js +0 -57
- package/src/strings/uk.js.map +0 -1
- package/src/strings/zh-CN.d.ts +0 -3
- package/src/strings/zh-CN.d.ts.map +0 -1
- package/src/strings/zh-CN.js +0 -57
- package/src/strings/zh-CN.js.map +0 -1
- package/src/template.d.ts +0 -13
- package/src/template.d.ts.map +0 -1
- package/src/template.js +0 -40
- package/src/template.js.map +0 -1
- package/src/translation-engine.d.ts +0 -9
- package/src/translation-engine.d.ts.map +0 -1
- package/src/translation-engine.js +0 -3
- package/src/translation-engine.js.map +0 -1
- package/src/translation-request.d.ts +0 -10
- package/src/translation-request.d.ts.map +0 -1
- package/src/translation-request.js +0 -3
- package/src/translation-request.js.map +0 -1
- package/src/translation-response.d.ts +0 -9
- package/src/translation-response.d.ts.map +0 -1
- package/src/translation-response.js +0 -3
- package/src/translation-response.js.map +0 -1
- package/src/types/engine.d.ts +0 -47
- package/src/types/engine.d.ts.map +0 -1
- package/src/types/engine.js +0 -8
- package/src/types/engine.js.map +0 -1
- package/src/types/index.d.ts.map +0 -1
- package/src/types/index.js +0 -9
- package/src/types/index.js.map +0 -1
- package/src/types/plural-types.d.ts.map +0 -1
- package/src/types/plural-types.js +0 -39
- package/src/types/plural-types.js.map +0 -1
- package/src/types.d.ts +0 -96
- package/src/types.d.ts.map +0 -1
- package/src/types.js +0 -23
- package/src/types.js.map +0 -1
- package/src/utils/currency.d.ts +0 -81
- package/src/utils/currency.d.ts.map +0 -1
- package/src/utils/currency.js +0 -101
- package/src/utils/currency.js.map +0 -1
- package/src/utils/html-escape.d.ts +0 -22
- package/src/utils/html-escape.d.ts.map +0 -1
- package/src/utils/html-escape.js +0 -53
- package/src/utils/html-escape.js.map +0 -1
- package/src/utils/index.d.ts.map +0 -1
- package/src/utils/index.js +0 -12
- package/src/utils/index.js.map +0 -1
- package/src/utils/lru-cache.d.ts +0 -42
- package/src/utils/lru-cache.d.ts.map +0 -1
- package/src/utils/lru-cache.js +0 -73
- package/src/utils/lru-cache.js.map +0 -1
- package/src/utils/plural-helpers.d.ts.map +0 -1
- package/src/utils/plural-helpers.js +0 -35
- package/src/utils/plural-helpers.js.map +0 -1
- package/src/utils/safe-object.d.ts +0 -39
- package/src/utils/safe-object.d.ts.map +0 -1
- package/src/utils/safe-object.js.map +0 -1
- package/src/utils/string-utils.d.ts +0 -28
- package/src/utils/string-utils.d.ts.map +0 -1
- package/src/utils/string-utils.js +0 -63
- package/src/utils/string-utils.js.map +0 -1
- package/src/utils/timezone.d.ts +0 -50
- package/src/utils/timezone.d.ts.map +0 -1
- package/src/utils/timezone.js +0 -74
- package/src/utils/timezone.js.map +0 -1
- package/src/utils/validation.d.ts +0 -40
- package/src/utils/validation.d.ts.map +0 -1
- package/src/utils/validation.js +0 -69
- package/src/utils/validation.js.map +0 -1
- package/src/utils.d.ts +0 -65
- package/src/utils.d.ts.map +0 -1
- package/src/utils.js +0 -129
- package/src/utils.js.map +0 -1
- package/src/validation/index.d.ts.map +0 -1
- package/src/validation/index.js +0 -5
- package/src/validation/index.js.map +0 -1
- package/src/validation/plural-validator.d.ts +0 -46
- package/src/validation/plural-validator.d.ts.map +0 -1
- package/src/validation/plural-validator.js +0 -123
- package/src/validation/plural-validator.js.map +0 -1
- package/src/validation-config.d.ts +0 -12
- package/src/validation-config.d.ts.map +0 -1
- package/src/validation-config.js +0 -3
- package/src/validation-config.js.map +0 -1
- package/src/validation-result.d.ts +0 -13
- package/src/validation-result.d.ts.map +0 -1
- package/src/validation-result.js +0 -3
- package/src/validation-result.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* String utility functions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { escapeHtml, safeStringify } from './html-escape';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Extract the actual value from an object that might be a wrapper (CurrencyCode, Timezone, etc.).
|
|
9
|
+
* @param value - The value to extract from
|
|
10
|
+
* @returns The extracted value or the original value if not a wrapper
|
|
11
|
+
*/
|
|
12
|
+
function extractValue(value: any): any {
|
|
13
|
+
// Handle objects with a 'value' property (CurrencyCode, Timezone, etc.)
|
|
14
|
+
if (value && typeof value === 'object' && 'value' in value && typeof value.value !== 'function') {
|
|
15
|
+
return value.value;
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Options for the replaceVariables function.
|
|
22
|
+
*/
|
|
23
|
+
export interface ReplaceVariablesOptions {
|
|
24
|
+
/** If true, HTML-escapes the replaced values */
|
|
25
|
+
escapeHtml?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Replaces variables in a string template with values from vars or constants.
|
|
30
|
+
* Variables are denoted by {variableName} in the template string.
|
|
31
|
+
* @param str - The template string containing variables
|
|
32
|
+
* @param vars - Optional object mapping variable names to values
|
|
33
|
+
* @param constants - Optional object containing constant values
|
|
34
|
+
* @param options - Optional configuration including HTML escaping
|
|
35
|
+
* @returns The string with variables replaced
|
|
36
|
+
*/
|
|
37
|
+
export function replaceVariables(
|
|
38
|
+
str: string,
|
|
39
|
+
vars?: Record<string, any>,
|
|
40
|
+
constants?: Record<string, any>,
|
|
41
|
+
options?: ReplaceVariablesOptions,
|
|
42
|
+
): string {
|
|
43
|
+
if (typeof str !== 'string') {
|
|
44
|
+
str = String(str);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const variables = str.match(/\{(.+?)\}/g);
|
|
48
|
+
if (!variables) return str;
|
|
49
|
+
|
|
50
|
+
let result = str;
|
|
51
|
+
for (const variable of variables) {
|
|
52
|
+
const varName = variable.slice(1, -1);
|
|
53
|
+
let replacement = '';
|
|
54
|
+
|
|
55
|
+
if (vars && varName in vars) {
|
|
56
|
+
const value = extractValue(vars[varName]);
|
|
57
|
+
replacement = safeStringify(value, options);
|
|
58
|
+
result = result.replace(variable, replacement);
|
|
59
|
+
} else if (constants && varName in constants) {
|
|
60
|
+
const value = extractValue(constants[varName]);
|
|
61
|
+
replacement = safeStringify(value, options);
|
|
62
|
+
result = result.replace(variable, replacement);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Checks if a string key indicates a template that expects variable replacement.
|
|
71
|
+
* Template keys end with 'template' (case-insensitive).
|
|
72
|
+
* @param key - The key to check
|
|
73
|
+
* @returns True if the key indicates a template, false otherwise
|
|
74
|
+
*/
|
|
75
|
+
export function isTemplate(key: string): boolean {
|
|
76
|
+
return key.trim().toLowerCase().endsWith('template');
|
|
77
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timezone utilities (v2)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import moment from 'moment-timezone';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Represents a valid timezone with validation.
|
|
9
|
+
* Uses moment-timezone for validation and timezone database.
|
|
10
|
+
*/
|
|
11
|
+
export class Timezone {
|
|
12
|
+
private readonly _value: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a new Timezone instance.
|
|
16
|
+
* @param timezone - The timezone name (e.g., 'America/New_York', 'UTC')
|
|
17
|
+
* @throws {Error} If the timezone is invalid
|
|
18
|
+
*/
|
|
19
|
+
constructor(timezone: string) {
|
|
20
|
+
if (!Timezone.isValid(timezone)) {
|
|
21
|
+
throw new Error(`Invalid timezone: ${timezone}`);
|
|
22
|
+
}
|
|
23
|
+
this._value = timezone;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Gets the timezone name.
|
|
28
|
+
* @returns The timezone name
|
|
29
|
+
*/
|
|
30
|
+
get value(): string {
|
|
31
|
+
return this._value;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Gets the timezone name (alias for value).
|
|
36
|
+
* @returns The timezone name
|
|
37
|
+
*/
|
|
38
|
+
get name(): string {
|
|
39
|
+
return this._value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Checks if a timezone name is valid.
|
|
44
|
+
* @param timezone - The timezone name to validate
|
|
45
|
+
* @returns True if the timezone is valid, false otherwise
|
|
46
|
+
*/
|
|
47
|
+
static isValid(timezone: string): boolean {
|
|
48
|
+
return moment.tz.zone(timezone) !== null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Gets all available timezone names.
|
|
53
|
+
* @returns Array of timezone names
|
|
54
|
+
*/
|
|
55
|
+
static getAll(): string[] {
|
|
56
|
+
return moment.tz.names();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Attempts to guess the user's timezone based on their system settings.
|
|
61
|
+
* @returns The guessed timezone name
|
|
62
|
+
*/
|
|
63
|
+
static guess(): string {
|
|
64
|
+
return moment.tz.guess();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Checks if a timezone name is valid.
|
|
70
|
+
* This is a convenience function that delegates to Timezone.isValid().
|
|
71
|
+
* @param timezone - The timezone name to validate
|
|
72
|
+
* @returns True if the timezone is valid, false otherwise
|
|
73
|
+
*/
|
|
74
|
+
export function isValidTimezone(timezone: string): boolean {
|
|
75
|
+
return Timezone.isValid(timezone);
|
|
76
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input validation utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Security limits for various input types to prevent abuse.
|
|
7
|
+
*/
|
|
8
|
+
export const LIMITS = {
|
|
9
|
+
MAX_TEMPLATE_LENGTH: 10000,
|
|
10
|
+
MAX_KEY_LENGTH: 200,
|
|
11
|
+
MAX_COMPONENT_ID_LENGTH: 100,
|
|
12
|
+
MAX_LANGUAGE_CODE_LENGTH: 10,
|
|
13
|
+
MAX_NESTING_DEPTH: 10,
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Validates that a template string does not exceed the maximum allowed length.
|
|
18
|
+
* @param template - The template string to validate
|
|
19
|
+
* @throws {Error} If the template exceeds the maximum length
|
|
20
|
+
*/
|
|
21
|
+
export function validateTemplateLength(template: string): void {
|
|
22
|
+
if (template.length > LIMITS.MAX_TEMPLATE_LENGTH) {
|
|
23
|
+
throw new Error(`Template exceeds maximum length of ${LIMITS.MAX_TEMPLATE_LENGTH}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Validates that a key does not exceed the maximum allowed length.
|
|
29
|
+
* @param key - The key to validate
|
|
30
|
+
* @throws {Error} If the key exceeds the maximum length
|
|
31
|
+
*/
|
|
32
|
+
export function validateKeyLength(key: string): void {
|
|
33
|
+
if (key.length > LIMITS.MAX_KEY_LENGTH) {
|
|
34
|
+
throw new Error(`Key exceeds maximum length of ${LIMITS.MAX_KEY_LENGTH}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Validates that a component ID meets length and character requirements.
|
|
40
|
+
* Component IDs must contain only alphanumeric characters, underscores, and hyphens.
|
|
41
|
+
* @param componentId - The component ID to validate
|
|
42
|
+
* @throws {Error} If the component ID is invalid
|
|
43
|
+
*/
|
|
44
|
+
export function validateComponentId(componentId: string): void {
|
|
45
|
+
if (componentId.length > LIMITS.MAX_COMPONENT_ID_LENGTH) {
|
|
46
|
+
throw new Error(`Component ID exceeds maximum length of ${LIMITS.MAX_COMPONENT_ID_LENGTH}`);
|
|
47
|
+
}
|
|
48
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(componentId)) {
|
|
49
|
+
throw new Error('Component ID contains invalid characters');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validates that a language code meets BCP 47 format requirements.
|
|
55
|
+
* Expected format: two lowercase letters, optionally followed by a hyphen and two uppercase letters (e.g., 'en', 'en-US').
|
|
56
|
+
* @param language - The language code to validate
|
|
57
|
+
* @throws {Error} If the language code is invalid
|
|
58
|
+
*/
|
|
59
|
+
export function validateLanguageCode(language: string): void {
|
|
60
|
+
if (language.length > LIMITS.MAX_LANGUAGE_CODE_LENGTH) {
|
|
61
|
+
throw new Error(`Language code exceeds maximum length of ${LIMITS.MAX_LANGUAGE_CODE_LENGTH}`);
|
|
62
|
+
}
|
|
63
|
+
if (!/^[a-z]{2}(-[A-Z]{2})?$/.test(language)) {
|
|
64
|
+
throw new Error('Invalid language code format');
|
|
65
|
+
}
|
|
66
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import moment from 'moment-timezone';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Replaces variables in a string with their corresponding values from vars or constants.
|
|
5
|
+
* @param str - The string containing variables to replace
|
|
6
|
+
* @param vars - An object mapping variable names to their replacement values
|
|
7
|
+
* @param constants - An object containing constant values for replacement
|
|
8
|
+
* @returns The string with variables replaced
|
|
9
|
+
*/
|
|
10
|
+
export function replaceVariables(
|
|
11
|
+
str: string,
|
|
12
|
+
vars?: Record<string, string | number>,
|
|
13
|
+
constants?: any,
|
|
14
|
+
): string {
|
|
15
|
+
// Ensure input is a string
|
|
16
|
+
if (typeof str !== 'string') {
|
|
17
|
+
str = String(str);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const variables = str.match(/\{(.+?)\}/g);
|
|
21
|
+
if (!variables) return str;
|
|
22
|
+
|
|
23
|
+
let result = str;
|
|
24
|
+
for (const variable of variables) {
|
|
25
|
+
const varName = variable.slice(1, -1);
|
|
26
|
+
let replacement = '';
|
|
27
|
+
|
|
28
|
+
if (vars && varName in vars) {
|
|
29
|
+
replacement = String(vars[varName]);
|
|
30
|
+
} else if (constants && varName in constants) {
|
|
31
|
+
replacement = String(constants[varName]);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (replacement) {
|
|
35
|
+
result = result.replace(variable, replacement);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Checks if a given key indicates a template string.
|
|
44
|
+
* @param key - The key to check
|
|
45
|
+
* @returns True if the key indicates a template, false otherwise
|
|
46
|
+
*/
|
|
47
|
+
export function isTemplate(key: string): boolean {
|
|
48
|
+
return key.trim().toLowerCase().endsWith('template');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Checks if a given timezone string is valid.
|
|
53
|
+
* @param timezone - The timezone string to validate
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
export function isValidTimezone(timezone: string): boolean {
|
|
57
|
+
return moment.tz.zone(timezone) !== null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Converts parts to a single string key, joining with underscores.
|
|
62
|
+
* @param parts - The parts to join
|
|
63
|
+
* @returns The joined string key
|
|
64
|
+
*/
|
|
65
|
+
export function toStringKey<TStringKey extends string>(
|
|
66
|
+
...parts: string[]
|
|
67
|
+
): TStringKey {
|
|
68
|
+
return parts.join('_') as TStringKey;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Converts an enum value to a string key by joining parts with underscores and appending the enum value.
|
|
73
|
+
* @param value - The enum value
|
|
74
|
+
* @param parts - Additional parts to join
|
|
75
|
+
* @returns The constructed string key
|
|
76
|
+
*/
|
|
77
|
+
export function toStringKeyFromEnum<TStringKey extends string>(
|
|
78
|
+
value: string,
|
|
79
|
+
...parts: string[]
|
|
80
|
+
): TStringKey {
|
|
81
|
+
const allParts = [...parts, value];
|
|
82
|
+
return allParts.join('_') as TStringKey;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Type that constructs string keys from enum values with prefixes and optional template suffix
|
|
87
|
+
*/
|
|
88
|
+
type BuildStringKey<
|
|
89
|
+
TEnumValue extends string,
|
|
90
|
+
TPrefixes extends readonly string[],
|
|
91
|
+
TIsTemplate extends boolean = false,
|
|
92
|
+
> = TPrefixes extends readonly []
|
|
93
|
+
? `${TEnumValue}${TIsTemplate extends true ? 'Template' : ''}`
|
|
94
|
+
: TPrefixes extends readonly [infer First, ...infer Rest]
|
|
95
|
+
? First extends string
|
|
96
|
+
? Rest extends readonly string[]
|
|
97
|
+
? `${First}_${BuildStringKey<TEnumValue, Rest, TIsTemplate>}`
|
|
98
|
+
: never
|
|
99
|
+
: never
|
|
100
|
+
: never;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Type that maps all enum values to their corresponding string keys
|
|
104
|
+
*/
|
|
105
|
+
type ReasonMapFromEnum<
|
|
106
|
+
TEnum extends Record<string, string>,
|
|
107
|
+
TStringKey extends string,
|
|
108
|
+
TPrefixes extends readonly string[] = [],
|
|
109
|
+
TTemplateKeys extends Set<TEnum[keyof TEnum]> = never,
|
|
110
|
+
> = {
|
|
111
|
+
[K in TEnum[keyof TEnum]]: BuildStringKey<
|
|
112
|
+
K,
|
|
113
|
+
TPrefixes,
|
|
114
|
+
TTemplateKeys extends Set<K> ? true : false
|
|
115
|
+
> extends TStringKey
|
|
116
|
+
? BuildStringKey<K, TPrefixes, TTemplateKeys extends Set<K> ? true : false>
|
|
117
|
+
: never;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Builds a reason map from an enum object, mapping each enum value to a string key.
|
|
122
|
+
* @param enumObj - The enum object
|
|
123
|
+
* @param prefixes - Prefixes to prepend to each string key
|
|
124
|
+
* @param templateKeys - Optional set of enum values that should have 'Template' suffix for template processing
|
|
125
|
+
* @returns The constructed reason map
|
|
126
|
+
*/
|
|
127
|
+
export function buildReasonMap<
|
|
128
|
+
TEnum extends Record<string, string>,
|
|
129
|
+
TStringKey extends string,
|
|
130
|
+
>(
|
|
131
|
+
enumObj: TEnum,
|
|
132
|
+
prefixes: string[] = [],
|
|
133
|
+
templateKeys?: Set<TEnum[keyof TEnum]>,
|
|
134
|
+
): Record<TEnum[keyof TEnum], TStringKey> {
|
|
135
|
+
const map = {} as Record<TEnum[keyof TEnum], TStringKey>;
|
|
136
|
+
|
|
137
|
+
Object.values(enumObj).forEach((value) => {
|
|
138
|
+
const baseKey = [...prefixes, value].join('_');
|
|
139
|
+
const finalKey = templateKeys?.has(value as TEnum[keyof TEnum])
|
|
140
|
+
? baseKey + 'Template'
|
|
141
|
+
: baseKey;
|
|
142
|
+
map[value as TEnum[keyof TEnum]] = finalKey as TStringKey;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return map;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Type-safe version of buildReasonMap that ensures all enum values are mapped and all string keys exist
|
|
150
|
+
*/
|
|
151
|
+
export function buildTypeSafeReasonMap<
|
|
152
|
+
TEnum extends Record<string, string>,
|
|
153
|
+
TStringKey extends string,
|
|
154
|
+
TPrefixes extends readonly string[] = [],
|
|
155
|
+
TTemplateKeys extends Set<TEnum[keyof TEnum]> = never,
|
|
156
|
+
>(
|
|
157
|
+
enumObj: TEnum,
|
|
158
|
+
prefixes: TPrefixes,
|
|
159
|
+
templateKeys?: TTemplateKeys,
|
|
160
|
+
): ReasonMapFromEnum<TEnum, TStringKey, TPrefixes, TTemplateKeys> {
|
|
161
|
+
const map: Partial<
|
|
162
|
+
ReasonMapFromEnum<TEnum, TStringKey, TPrefixes, TTemplateKeys>
|
|
163
|
+
> = {};
|
|
164
|
+
|
|
165
|
+
Object.values(enumObj).forEach((value) => {
|
|
166
|
+
const baseKey = [...prefixes, value].join('_');
|
|
167
|
+
const finalKey = templateKeys?.has(value as TEnum[keyof TEnum])
|
|
168
|
+
? baseKey + 'Template'
|
|
169
|
+
: baseKey;
|
|
170
|
+
map[value as TEnum[keyof TEnum]] = finalKey as any;
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
return map as ReasonMapFromEnum<TEnum, TStringKey, TPrefixes, TTemplateKeys>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Validates that a reason map has entries for all enum values
|
|
178
|
+
*/
|
|
179
|
+
export function validateReasonMap<
|
|
180
|
+
TEnum extends Record<string, string>,
|
|
181
|
+
TStringKey extends string,
|
|
182
|
+
>(
|
|
183
|
+
enumObj: TEnum,
|
|
184
|
+
reasonMap: Partial<Record<TEnum[keyof TEnum], TStringKey>>,
|
|
185
|
+
): reasonMap is Record<TEnum[keyof TEnum], TStringKey> {
|
|
186
|
+
return Object.values(enumObj).every(
|
|
187
|
+
(value) =>
|
|
188
|
+
value in reasonMap &&
|
|
189
|
+
reasonMap[value as TEnum[keyof TEnum]] !== undefined,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Creates a complete reason map ensuring all enum values are covered
|
|
195
|
+
*/
|
|
196
|
+
export function createCompleteReasonMap<
|
|
197
|
+
TEnum extends Record<string, string>,
|
|
198
|
+
TStringKey extends string,
|
|
199
|
+
>(
|
|
200
|
+
enumObj: TEnum,
|
|
201
|
+
prefixes: readonly string[] = [],
|
|
202
|
+
templateKeys?: Set<TEnum[keyof TEnum]>,
|
|
203
|
+
): Record<TEnum[keyof TEnum], TStringKey> {
|
|
204
|
+
const map = buildReasonMap(enumObj, [...prefixes], templateKeys) as Record<
|
|
205
|
+
TEnum[keyof TEnum],
|
|
206
|
+
TStringKey
|
|
207
|
+
>;
|
|
208
|
+
|
|
209
|
+
if (!validateReasonMap(enumObj, map)) {
|
|
210
|
+
const missing = Object.values(enumObj).filter((value) => !(value in map));
|
|
211
|
+
throw new Error(`Missing reason map entries for: ${missing.join(', ')}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return map;
|
|
215
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plural form validation
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { PluralCategory } from '../pluralization/plural-categories';
|
|
6
|
+
import { PluralString, isPluralString } from '../types/plural-types';
|
|
7
|
+
import { getRequiredPluralForms, getAllPluralForms } from '../pluralization/language-plural-map';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Result of validating plural forms.
|
|
11
|
+
*/
|
|
12
|
+
export interface PluralValidationResult {
|
|
13
|
+
/** Whether the validation passed */
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
/** Array of validation errors */
|
|
16
|
+
errors: string[];
|
|
17
|
+
/** Array of validation warnings */
|
|
18
|
+
warnings: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for plural form validation.
|
|
23
|
+
*/
|
|
24
|
+
export interface PluralValidationOptions {
|
|
25
|
+
/** If true, treat missing required forms as errors instead of warnings */
|
|
26
|
+
strict?: boolean;
|
|
27
|
+
/** If true, warn about unused plural forms */
|
|
28
|
+
checkUnused?: boolean;
|
|
29
|
+
/** If true, check for consistent variable usage across forms */
|
|
30
|
+
checkVariables?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Validate plural forms for a specific language.
|
|
35
|
+
* Checks that all required plural forms are present and optionally validates variable consistency.
|
|
36
|
+
* @param value - The plural string value to validate
|
|
37
|
+
* @param language - The language code
|
|
38
|
+
* @param key - The translation key (for error messages)
|
|
39
|
+
* @param options - Validation options
|
|
40
|
+
* @returns Validation result with errors and warnings
|
|
41
|
+
*/
|
|
42
|
+
export function validatePluralForms(
|
|
43
|
+
value: PluralString,
|
|
44
|
+
language: string,
|
|
45
|
+
key: string,
|
|
46
|
+
options: PluralValidationOptions = {}
|
|
47
|
+
): PluralValidationResult {
|
|
48
|
+
const errors: string[] = [];
|
|
49
|
+
const warnings: string[] = [];
|
|
50
|
+
|
|
51
|
+
if (!isPluralString(value)) {
|
|
52
|
+
return { isValid: true, errors, warnings };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const required = getRequiredPluralForms(language);
|
|
56
|
+
const all = getAllPluralForms(language);
|
|
57
|
+
const provided = Object.keys(value) as PluralCategory[];
|
|
58
|
+
|
|
59
|
+
// Check required forms
|
|
60
|
+
for (const form of required) {
|
|
61
|
+
if (!value[form as PluralCategory]) {
|
|
62
|
+
if (options.strict) {
|
|
63
|
+
errors.push(`Missing required plural form '${form}' for language '${language}' in key '${key}'`);
|
|
64
|
+
} else {
|
|
65
|
+
warnings.push(`Missing required plural form '${form}' for language '${language}' in key '${key}'`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check unused forms
|
|
71
|
+
if (options.checkUnused) {
|
|
72
|
+
for (const form of provided) {
|
|
73
|
+
if (!all.includes(form)) {
|
|
74
|
+
warnings.push(`Unused plural form '${form}' for language '${language}' in key '${key}'`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Check variable consistency
|
|
80
|
+
if (options.checkVariables) {
|
|
81
|
+
const variables = extractVariables(value);
|
|
82
|
+
const inconsistent = findInconsistentVariables(value, variables);
|
|
83
|
+
for (const [form, missing] of Object.entries(inconsistent)) {
|
|
84
|
+
warnings.push(`Plural form '${form}' in key '${key}' missing variables: ${missing.join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
isValid: errors.length === 0,
|
|
90
|
+
errors,
|
|
91
|
+
warnings,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Extract all variables from plural forms.
|
|
97
|
+
* Scans all plural form texts for {variable} patterns.
|
|
98
|
+
* @param value - The plural string value
|
|
99
|
+
* @returns Set of all variable names found
|
|
100
|
+
*/
|
|
101
|
+
function extractVariables(value: PluralString): Set<string> {
|
|
102
|
+
const vars = new Set<string>();
|
|
103
|
+
if (typeof value === 'string') return vars;
|
|
104
|
+
|
|
105
|
+
for (const text of Object.values(value)) {
|
|
106
|
+
if (text) {
|
|
107
|
+
const matches = text.match(/\{(\w+)\}/g);
|
|
108
|
+
if (matches) {
|
|
109
|
+
matches.forEach(m => vars.add(m.slice(1, -1)));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return vars;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Find forms with inconsistent variables.
|
|
118
|
+
* Identifies plural forms that are missing variables used in other forms.
|
|
119
|
+
* @param value - The plural string value
|
|
120
|
+
* @param allVars - Set of all variables found across all forms
|
|
121
|
+
* @returns Object mapping form names to arrays of missing variable names
|
|
122
|
+
*/
|
|
123
|
+
function findInconsistentVariables(
|
|
124
|
+
value: PluralString,
|
|
125
|
+
allVars: Set<string>
|
|
126
|
+
): Record<string, string[]> {
|
|
127
|
+
const inconsistent: Record<string, string[]> = {};
|
|
128
|
+
if (typeof value === 'string') return inconsistent;
|
|
129
|
+
|
|
130
|
+
for (const [form, text] of Object.entries(value)) {
|
|
131
|
+
if (text) {
|
|
132
|
+
const formVars = new Set<string>();
|
|
133
|
+
const matches = text.match(/\{(\w+)\}/g);
|
|
134
|
+
if (matches) {
|
|
135
|
+
matches.forEach(m => formVars.add(m.slice(1, -1)));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const missing = Array.from(allVars).filter(v => !formVars.has(v));
|
|
139
|
+
if (missing.length > 0) {
|
|
140
|
+
inconsistent[form] = missing;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return inconsistent;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Validate that count variable exists when plural forms are used.
|
|
149
|
+
* Pluralization requires a 'count' variable to determine which form to use.
|
|
150
|
+
* @param value - The plural string value
|
|
151
|
+
* @param variables - The variables object to check
|
|
152
|
+
* @param key - The translation key (for error messages)
|
|
153
|
+
* @returns Validation result with warnings if count is missing
|
|
154
|
+
*/
|
|
155
|
+
export function validateCountVariable(
|
|
156
|
+
value: PluralString,
|
|
157
|
+
variables: Record<string, any> | undefined,
|
|
158
|
+
key: string
|
|
159
|
+
): PluralValidationResult {
|
|
160
|
+
const errors: string[] = [];
|
|
161
|
+
const warnings: string[] = [];
|
|
162
|
+
|
|
163
|
+
if (isPluralString(value) && (!variables || variables.count === undefined)) {
|
|
164
|
+
warnings.push(`Plural forms used in key '${key}' but no 'count' variable provided`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return { isValid: true, errors, warnings };
|
|
168
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for component registration validation
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationConfig {
|
|
5
|
+
/** Whether to require all languages to have all strings */
|
|
6
|
+
readonly requireCompleteStrings: boolean;
|
|
7
|
+
/** Whether to allow registration with missing strings (will use fallbacks) */
|
|
8
|
+
readonly allowPartialRegistration: boolean;
|
|
9
|
+
/** Default language to fall back to for missing strings */
|
|
10
|
+
readonly fallbackLanguageId: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation result for component registration
|
|
3
|
+
*/
|
|
4
|
+
export interface ValidationResult {
|
|
5
|
+
readonly isValid: boolean;
|
|
6
|
+
readonly missingKeys: ReadonlyArray<{
|
|
7
|
+
readonly languageId: string;
|
|
8
|
+
readonly componentId: string;
|
|
9
|
+
readonly stringKey: string;
|
|
10
|
+
}>;
|
|
11
|
+
readonly errors: readonly string[];
|
|
12
|
+
}
|
package/src/active-context.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { CurrencyCode } from './utils/currency';
|
|
2
|
-
import { Timezone } from './utils/timezone';
|
|
3
|
-
import { LanguageContextSpace } from './types';
|
|
4
|
-
/**
|
|
5
|
-
* Represents the active internationalization context for user and admin interfaces,
|
|
6
|
-
* including language, currency, and timezone settings.
|
|
7
|
-
*
|
|
8
|
-
* @template TLanguage The type of language codes (e.g., 'en-US', 'fr').
|
|
9
|
-
*/
|
|
10
|
-
export interface IActiveContext<TLanguage extends string> {
|
|
11
|
-
/**
|
|
12
|
-
* The default language for the user-facing application.
|
|
13
|
-
*/
|
|
14
|
-
language: TLanguage;
|
|
15
|
-
/**
|
|
16
|
-
* The default language for the admin interface.
|
|
17
|
-
*/
|
|
18
|
-
adminLanguage: TLanguage;
|
|
19
|
-
/**
|
|
20
|
-
* The default currency code for the user-facing application.
|
|
21
|
-
*/
|
|
22
|
-
currencyCode: CurrencyCode;
|
|
23
|
-
/**
|
|
24
|
-
* The current language context space (e.g., 'user' or 'admin').
|
|
25
|
-
*/
|
|
26
|
-
currentContext: LanguageContextSpace;
|
|
27
|
-
/**
|
|
28
|
-
* The default timezone for the user-facing application.
|
|
29
|
-
*/
|
|
30
|
-
timezone: Timezone;
|
|
31
|
-
/**
|
|
32
|
-
* The default timezone for the admin interface.
|
|
33
|
-
*/
|
|
34
|
-
adminTimezone: Timezone;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=active-context.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"active-context.d.ts","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/active-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,WAAW,cAAc,CAAC,SAAS,SAAS,MAAM;IACtD;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,aAAa,EAAE,SAAS,CAAC;IAEzB;;OAEG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B;;OAEG;IACH,cAAc,EAAE,oBAAoB,CAAC;IAErC;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC;IAEnB;;OAEG;IACH,aAAa,EAAE,QAAQ,CAAC;CACzB"}
|
package/src/active-context.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"active-context.js","sourceRoot":"","sources":["../../../../packages/digitaldefiance-i18n-lib/src/active-context.ts"],"names":[],"mappings":""}
|