Skip to content

i18n support for standard errors, without specifying x-errors in openapi #214

@Xeej

Description

@Xeej

I needed to translate standard errors that are hardcoded in Vocab for my project. I didn't want to redefine all the error methods def error, so I made a hack that helped me translate standard errors using i18n. This required passing additional parameters to i18n!, but I would like to be able to rename such errors more transparently. Perhaps this is not bad for a temporary solution, but the current architecture has a hard time accepting the use of errors with i18n without specifying the translation in the openapi

MonkeyPatch: lib/json_schemer/result.rb

module JSONSchemer
  class Result
    def i18n!
      base_uri_str = source.schema.base_uri.to_s
      meta_schema_base_uri_str = source.schema.meta_schema.base_uri.to_s
      resolved_keyword_location = Location.resolve(keyword_location)
      resolved_instance_location = Location.resolve(instance_location)
      formatted_instance_location = resolved_instance_location.empty? ? 'root' : "`#{resolved_instance_location}`"
      error_key = source.error_key
      I18n.translate!(
        source.absolute_keyword_location,
        :default => [
          "#{base_uri_str}#{I18N_SEPARATOR}##{resolved_keyword_location}",
          "##{resolved_keyword_location}",
          "#{base_uri_str}#{I18N_SEPARATOR}#{error_key}",
          "#{base_uri_str}#{I18N_SEPARATOR}#{CATCHALL}",
          "#{meta_schema_base_uri_str}#{I18N_SEPARATOR}#{error_key}",
          "#{meta_schema_base_uri_str}#{I18N_SEPARATOR}#{CATCHALL}",
          error_key,
          CATCHALL
        ].map!(&:to_sym),
        :separator => I18N_SEPARATOR,
        :scope => I18N_ERRORS_SCOPE,
        :instance => instance,
        :instanceLocation => formatted_instance_location,
        :keywordLocation => resolved_keyword_location,
        :absoluteKeywordLocation => source.absolute_keyword_location,
        :missing_keys => details&.fetch('missing_keys')&.join(', '),
        :value => source.value
      )
    end
  end
end

it's not hard at all to compare what has changed :) there aren't that many

example ru.json_schemer.yml

---
ru:
  json_schemer:
    errors:
      properties: "Cвойства объекта в %{instanceLocation} не соответствует схеме `properties`"
      then: "Cвойства объекта в %{instanceLocation} не соответствует схеме `then`"
      allOf: "Cвойства объекта в %{instanceLocation} не соответствует всем схемам `allOf`"
      anyOf: "Cвойства объекта в %{instanceLocation} не соответствует ни одной схеме `anyOf`"
      oneOf: "Cвойства объекта в %{instanceLocation} не соответствует хотябы одной схеме `oneOf`"
      not: "Cвойства объекта в %{instanceLocation} не соответствует хотябы одной схеме `not`"
      else: "Cвойства объекта в %{instanceLocation} не соответствует схеме `else`"
      dependentSchemas: "Cвойства объекта в %{instanceLocation} не применимы схеме `dependentSchemas`"
      prefixItems: "Cвойства объекта в %{instanceLocation} не соответствует схеме `prefixItems`"
      array: "Массив свойств объекта в %{instanceLocation} не соответствует схеме `items`"
      contains: "Массив свойств объекта в %{instanceLocation} не содержит достаточного кол-ва элементов схемы `contains`"
      patternProperties: "Cвойства объекта в %{instanceLocation} не соответствует схеме `patternProperties`"
      additionalProperties: "Cвойства объекта в %{instanceLocation} не соответствует схеме `additionalProperties`"
      propertyNames: "Имя объекта в %{instanceLocation} не соответствует схеме `propertyNames`"
      dependencies: "Объект в %{instanceLocation} либо не соответствует схеме `dependencies`, либо в нем отсутствуют требуемые свойства `dependencies`"
      format: "Значение в %{instanceLocation} имеет неверный формат: `%{value}`"
      readOnly: "Значение в %{instanceLocation} является `readOnly`"
      writeOnly: "Значение в %{instanceLocation} является `writeOnly`"
      exclusiveMaximum: "Число в %{instanceLocation} больше или равно `maximum`"
      exclusiveMinimum: "Число в %{instanceLocation} меньше или равно `minimum`"
      discriminator: "Значение в %{instanceLocation} не соответствует схеме `discriminator`"
      type: "Значение в %{instanceLocation} должен иметь тип: `%{value}`"
      enum: "Значение в %{instanceLocation} не одно из `%{value}`"
      const: "Значение в %{instanceLocation} не `%{value}`"
      multipleOf: "Число в %{instanceLocation} не является кратным: `%{value}`"
      maximum: "Число в %{instanceLocation} больше чем: `%{value}`"
      minimum: "Число в %{instanceLocation} меньше чем: `%{value}`"
      maxLength: "Длинна строки в %{instanceLocation} больше чем: `%{value}`"
      minLength: "Длинна строки в %{instanceLocation} меньше чем: `%{value}`"
      pattern: "Строка в %{instanceLocation} не соответствует регулярному выражению: `%{value}`"
      maxItems: "Размер массива в %{instanceLocation} больше чем: `%{value}`"
      minItems: "Размер массива в %{instanceLocation} меньше чем: `%{value}`"
      uniqueItems: "Элементы массива в %{instanceLocation} не уникальны"
      maxContains: "Кол-во элементов массива в %{instanceLocation} не соответсвуют схеме `contains`, больше чем %{value}"
      minContains: "Кол-во элементов массива в %{instanceLocation} не соответсвуют схеме `contains`, меньше чем %{value}"
      maxProperties: "Максимальное кол-во объектов в %{instanceLocation} больше чем %{value}"
      minProperties: "Минимальное кол-во объектов в %{instanceLocation} больше чем %{value}"
      required: "В объекте %{instanceLocation} не переданы обязательные свойства: %{missing_keys}"
      dependentRequired: "Cвойства объекта в %{instanceLocation} не соответствует схеме `dependentRequired`"
      '*': "Значение в %{instanceLocation} не соответствует схеме"

'*': - since the JSONShemer::Shema class also has def error
This way you can translate into any language you need.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions