validator icon indicating copy to clipboard operation
validator copied to clipboard

enum or enumSet is not working with i18n JSON

Open darshithedpara opened this issue 2 years ago • 8 comments

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"
    ]
}

darshithedpara avatar Aug 12 '23 18:08 darshithedpara

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

thetutlage avatar Aug 13 '23 02:08 thetutlage

@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 avatar Aug 13 '23 07:08 darshithedpara

Is anyone else facing the same issue?

darshithedpara avatar Aug 21 '23 04:08 darshithedpara

Hey @darshithedpara! 👋🏻

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

RomainLanz avatar Sep 11 '23 19:09 RomainLanz

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 avatar Sep 15 '23 05:09 darshithedpara

@RomainLanz You able to reproduce this issue?

darshithedpara avatar Sep 21 '23 17:09 darshithedpara

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 }"

RomainLanz avatar Sep 23 '23 20:09 RomainLanz

@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

darshithedpara avatar Sep 24 '23 05:09 darshithedpara