adonisjs / validator

Schema based validator for AdonisJS
MIT License
115 stars 40 forks source link

enum or enumSet is not working with i18n JSON #172

Open darshithedpara opened 1 year ago

darshithedpara commented 1 year ago

Package version :

"@adonisjs/ally": "^4.1.5",
"@adonisjs/auth": "^8.2.3",
"@adonisjs/bouncer": "^2.3.0",
"@adonisjs/core": "^5.9.0",
"@adonisjs/i18n": "^1.6.0",
"@adonisjs/lucid": "^18.4.0",
"@adonisjs/repl": "^3.1.11",
"adonis5-swagger": "^1.4.1",
"luxon": "^3.3.0",
"@adonisjs/assembler": "^5.9.5",
"@japa/preset-adonis": "^1.2.0",
"@japa/runner": "^2.5.1",
"@types/proxy-addr": "^2.0.0",
"@types/source-map-support": "^0.5.6",
"adonis-preset-ts": "^2.1.0",
"pino-pretty": "^10.0.1",
"typescript": "~4.6",
"youch": "^3.2.3",
"youch-terminal": "^2.2.2"

Node.js :

9.5.1

npm version :

v18.16.1

Sample Code (to reproduce the issue)

❌ Not Working when we defined custom messages in i18n JSON :

1] Source :

import {schema, CustomMessages, validator, rules} from '@ioc:Adonis/Core/Validator'
import type {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'

enum SocialAccounts {
  GOOGLE = 'google',
  TWITTER = 'twitter',
  FACEBOOK = 'facebook',
  INSTAGRAM = 'instagram',
  LINKEDIN = 'linkedin',
}

export default class SocialRequestValidator {
  constructor(protected ctx: HttpContextContract) {
  }

  public reporter = validator.reporters.vanilla

  public schema = schema.create({
    provider_name:  schema.enum(Object.values(SocialAccounts)),
  })

  private messages = this.ctx.i18n.validatorMessages('validator.social')
}

Validator JSON : location for json file : resources/lang/en/validator.json

{
  "social": {
    "provider_name.enum": "provider name is not supported, supported provider is {{options.choices}}"
  }
}

1] Source output :

{
    "message": "MALFORMED_ARGUMENT",
    "stack": "SyntaxError: MALFORMED_ARGUMENT\n    at Function.parse [as __parse] (/node_modules/@formatjs/icu-messageformat-parser/index.js:34:21)\n    at new IntlMessageFormat (/node_modules/intl-messageformat/src/core.js:140:42)\n    at IcuFormatter.format (/node_modules/@adonisjs/i18n/build/src/Formatters/Message/Icu.js:54:16)\n    at I18n.formatRawMessage (/node_modules/@adonisjs/i18n/build/src/I18n/index.js:204:48)\n    at I18n.formatValidatorMessage (/node_modules/@adonisjs/i18n/build/src/I18n/index.js:100:21)\n    at MessagesBag.* [as wildCardCallback] (/node_modules/@adonisjs/i18n/build/src/I18n/index.js:138:47)\n    at MessagesBag.get (/node_modules/@adonisjs/validator/build/src/MessagesBag/index.js:58:24)\n    at VanillaErrorReporter.report (/node_modules/@adonisjs/validator/build/src/ErrorReporter/Vanilla.js:38:49)\n    at Object.validate (/node_modules/@adonisjs/validator/build/src/Validations/primitives/enum.js:53:27)\n    at eval (eval at compile (/node_modules/@adonisjs/validator/build/src/Compiler/index.js:218:16), <anonymous>:128:36)"
}
✅ Working when we defined custom messages inside validator class itself :

2] Source :

import {schema, CustomMessages, validator, rules} from '@ioc:Adonis/Core/Validator'
import type {HttpContextContract} from '@ioc:Adonis/Core/HttpContext'

enum SocialAccounts {
  GOOGLE = 'google',
  TWITTER = 'twitter',
  FACEBOOK = 'facebook',
  INSTAGRAM = 'instagram',
  LINKEDIN = 'linkedin',
}

export default class SocialRequestValidator {
  constructor(protected ctx: HttpContextContract) {
  }

  public reporter = validator.reporters.vanilla

  public schema = schema.create({
    provider_name:  schema.enum(Object.values(SocialAccounts)),
  })

  public messages: CustomMessages = {
    "provider_name.enum": "provider name is not supported, supported provider is {{ options.choices }}"
  }
}

2] Source output :

{
    "provider_name": [
        "provider name is not supported, supported provider is google,twitter,facebook,instagram,linkedin"
    ]
}
thetutlage commented 1 year ago

Because you interpolation syntax is wrong with i18n messages. Check this guide https://docs.adonisjs.com/guides/i18n#interpolation

darshithedpara commented 1 year ago

@thetutlage Do you mean in Validator.json I need to use a single curly brace for referencing dynamic values? I tried that already but it gives me the same error.

It's working for others and not working for enum and enumSet

{
  "errors": {
    "somethingWentWrong": "Something went wrong.!",
    "unauthorizedAccess": "Unauthorized access.!",
    "dontHavePermission": "You don't have access to perform this action.!",
    "validationFailed": "validation failed.!"
  },
  "crud": {
    "list": "{item} fetched successfully.!",
    "show": "{item} fetched successful.!",
    "create": "{item} create successful.!",
    "update": "{item} update successful.!",
    "delete": "{item} deleted successful.!",
    "notFound": "{item} not found.!"
  }
}

image

darshithedpara commented 1 year ago

Is anyone else facing the same issue?

RomainLanz commented 1 year ago

Hey @darshithedpara! 👋🏻

It would be easier if you could share a repository with the minimum amount of code to reproduce your issue.

darshithedpara commented 1 year ago

Hello @RomainLanz

You can find the sample code and postman collection here. enum-test-poc.zip Enum Test.postman_collection.zip


I have created 2 validator request, one with i18n json and in another one I have defined the validatgion messages directly to validator class : 1] image image


2] image image

darshithedpara commented 1 year ago

@RomainLanz You able to reproduce this issue?

RomainLanz commented 12 months ago

As said per @thetutlage, your interpolation is wrong. ICU messages syntax does not support nested data, so everything is flattened. You can access the property by referencing choices directly.

Change your i18n message by the following and it should work:

"provider_name.enum": "provider name is not supported - EN { choices }"
darshithedpara commented 12 months ago

@RomainLanz Yes with flattened it is working but it is producing different results.

1] With messages property in validator class : (Here choices are coming as comma-separated string) image

image


2] With i18n JSON : (Here choices are coming as Array of string) image

image

image