{"id":30947500,"url":"https://github.com/siili-core/humanize","last_synced_at":"2025-12-12T01:19:05.363Z","repository":{"id":49808916,"uuid":"123299584","full_name":"siili-core/humanize","owner":"siili-core","description":"Translate computer produced garble into human readable form","archived":false,"fork":false,"pushed_at":"2018-09-14T09:57:13.000Z","size":24,"stargazers_count":17,"open_issues_count":1,"forks_count":1,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-08-06T20:56:16.699Z","etag":null,"topics":["clojure","humanize","schema","translator"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siili-core.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-02-28T14:53:40.000Z","updated_at":"2023-05-27T05:38:29.000Z","dependencies_parsed_at":"2022-09-14T11:02:01.276Z","dependency_job_id":null,"html_url":"https://github.com/siili-core/humanize","commit_stats":null,"previous_names":["siilisolutions/humanize"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/siili-core/humanize","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siili-core%2Fhumanize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siili-core%2Fhumanize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siili-core%2Fhumanize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siili-core%2Fhumanize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siili-core","download_url":"https://codeload.github.com/siili-core/humanize/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siili-core%2Fhumanize/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274547925,"owners_count":25306029,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-10T02:00:12.551Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","humanize","schema","translator"],"created_at":"2025-09-11T01:14:48.090Z","updated_at":"2025-12-12T01:19:05.295Z","avatar_url":"https://github.com/siili-core.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"#  \u0026#129302; `(humanize ex)` \u0026#128522;\n\nLibrary for translating errors into human readable form.\n\n[![License](https://img.shields.io/badge/License-EPL%201.0-red.svg)](https://opensource.org/licenses/EPL-1.0) [![CircleCI](https://img.shields.io/circleci/project/github/siilisolutions/humanize.svg)](https://circleci.com/gh/siilisolutions/humanize) [![cljdoc badge](https://cljdoc.xyz/badge/siili/humanize)](https://cljdoc.xyz/d/siili/humanize/CURRENT)\n\n## Installation\n\nAdd `siili/humanize` to your project:\n[![Clojars Project](https://img.shields.io/clojars/v/siili/humanize.svg)](https://clojars.org/siili/humanize)\n\n\u003e Not sure if humanize is for you? We recommend testing it with [`lein try`](https://github.com/rkneufeld/lein-try)!\n\n## Usage\n\nBase usage is very simple:\n 1. Require namespace you need\n 1. Use `ex-\u003eerr` function from humanize's namespace to convert exceptions into translated error data\n 1. Use that data in any way you please\n\n### Translated error data format\n\n - The main data structure is always a map\n - There are three keywords which describe where the error(s) occurred:\n   - `:in` input to function is faulty\n   - `:out` function's output is faulty\n   - `:unknown` faulty data occurred in unspecified location\n - `:in` is a vector where each entry describes one argument to function in the same order as they are defined in function signature\n - `:out` is a single value\n - `:unknown` is unspecified\n\n### Example: with [Plumatic Schema](https://github.com/plumatic/schema)\n\n```clojure\n;;  require needed namespaces\n(require '[schema.core :as s]\n         '[humanize.schema :as h])\n\n;;  humanize is meant for interop with s/defn functions\n(s/defn broken :- s/Str\n  [x :- s/Int]\n  x)\n\n;;  boilerplate for calling the broken function in invalid way\n(defn check [f]\n  (try\n    (f)\n    (catch clojure.lang.ExceptionInfo e\n      (if (= (-\u003e e ex-data :type)\n             :schema.core/error)\n        (h/ex-\u003eerr e)))))\n\n(check #(broken \"two\"))\n\n=\u003e {:in ([x \"'two' is not an integer.\"])}\n```\n\n## Extending\n\nHumanize can only handle the built-in types and structures. For user defined types an additional translator function can be provided to utilize humanize's internal resolver logic.\n\nFor example, assuming the following regular expression checking variant schema has been defined by user:\n```clojure\n(ns my.ns\n  (:require [schema.core :as s]\n            [schema.spec.variant :as variant]\n            [schema.spec.core :as spec]))\n\n(defrecord RegexString [regex]\n  s/Schema\n  (spec [this]\n    (variant/variant-spec\n     spec/+no-precondition+\n     [{:schema s/Str}]\n     nil\n     ;; take special note of this line, the list at the end is important\n     (spec/precondition this (partial re-matches regex) #(list 'not-matching regex %))))\n  (explain [this]\n    (list 'regex-constrained (s/explain s/Str) regex)))\n```\n\nwhich is then used to define a custom validator:\n```clojure\n(def AtoZ (RegexString. #\"[AZ]+\"))\n\n(s/defn yelling-alphas :- s/Any\n  [aagh :- AtoZ]\n  aagh)\n```\nrunning this through humanize in same manner as above would produce unresolved translation:\n```clojure\n(check #(yelling-alphas \"123\"))\n\n=\u003e {:in ([aagh [not [not-matching #\"[AZ]+\" \"123\"]]])}\n```\nwhich isn't that useful. To resolve this, simply provide a additional translations function to `ex-\u003eerr`:\n```clojure\n(defn check [f additional-translations]\n  (try\n    (f)\n    (catch clojure.lang.ExceptionInfo e\n      (if (= (-\u003e e ex-data :type)\n             :schema.core/error)\n        (h/ex-\u003eerr e additional-translations)))))\n```\nand call it with your own logic (we recommend [clojure/core.match](https://github.com/clojure/core.match)) to get the desired result:\n\n```clojure\n(defn my-translate [x]\n  (clojure.core.match/match\n    x\n    ;; this matches with the spec/precondition list in variant spec\n    ['not ['not-matching regex-pattern value]]\n    (str value \" does not match regex pattern \" regex-pattern)\n\n    :else\n    x))\n\n(check #(yelling-alphas \"123\") my-translate)\n=\u003e {:in ([aagh \"123 does not match regex pattern [AZ]+\"])}\n```\n\n## Acknowledgements\n\n[André Rauh](https://gist.github.com/rauhs/cfdb55a8314e0d3f4862) for the original Plumatic Schema exception unroller.\n\n## Related Work\n\n - For [`spec.alpha`](https://github.com/clojure/spec.alpha) see [bhb/expound](https://github.com/bhb/expound)\n - For older versions of Schema and additionally Avro, datomic, etc. see [cddr/integrity](https://github.com/cddr/integrity)\u003cbr /\u003e\n It is possible some of the features of this library will find their way to humanize eventually\n\n## License\n\nCopyright © 2018 Siili Solutions\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiili-core%2Fhumanize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiili-core%2Fhumanize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiili-core%2Fhumanize/lists"}