├── .eslintrc.js ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── build.yml │ └── publish.yml ├── .gitignore ├── .gitmodules ├── .npmrc ├── .prettierignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── karma.conf.js ├── localize ├── .eslintrc.yml ├── README.md ├── index.d.jst ├── index.jst ├── localize.d.jst ├── localize.jst └── types.d.ts ├── messages ├── index.js └── jtd.js ├── package.json ├── scripts ├── .eslintrc.yml ├── compile-locales.js └── prepare-tests └── spec ├── .eslintrc.yml ├── localize-jtd.spec.js ├── localize.spec.js └── style.spec.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const jsConfig = require("@ajv-validator/config/.eslintrc_js") 2 | 3 | module.exports = { 4 | env: { 5 | es6: true, 6 | node: true, 7 | }, 8 | overrides: [ 9 | { 10 | ...jsConfig, 11 | rules: { 12 | semi: [2, "never"], 13 | }, 14 | }, 15 | ], 16 | } 17 | 18 | // extends: eslint:recommended 19 | // env: 20 | // node: true 21 | // browser: true 22 | // parserOptions: 23 | // ecmaVersion: 2018 24 | // rules: 25 | // block-scoped-var: 2 26 | // callback-return: 2 27 | // curly: [2, multi-or-nest, consistent] 28 | // dot-location: [2, property] 29 | // dot-notation: 2 30 | // indent-legacy: [2, 2, SwitchCase: 1] 31 | // linebreak-style: [2, unix] 32 | // new-cap: 2 33 | // no-console: [2, allow: [warn, error]] 34 | // no-else-return: 2 35 | // no-eq-null: 2 36 | // no-fallthrough: 2 37 | // no-invalid-this: 2 38 | // no-return-assign: 2 39 | // no-shadow: 1 40 | // no-trailing-spaces: 2 41 | // no-use-before-define: [2, nofunc] 42 | // quotes: [2, single, avoid-escape] 43 | // semi: [2, always] 44 | // strict: [2, global] 45 | // valid-jsdoc: [2, requireReturn: false] 46 | // no-control-regex: 0 47 | // no-useless-escape: 2 48 | // no-tabs: 2 49 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: epoberezkin 2 | tidelift: "npm/ajv-i18n" 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: karma 10 | versions: 11 | - 6.0.3 12 | - 6.0.4 13 | - 6.1.0 14 | - 6.1.1 15 | - 6.1.2 16 | - 6.2.0 17 | - 6.3.0 18 | - 6.3.1 19 | - dependency-name: ajv 20 | versions: 21 | - 7.0.3 22 | - 7.0.4 23 | - 7.1.0 24 | - 7.1.1 25 | - 7.2.1 26 | - 7.2.3 27 | - dependency-name: browserify 28 | versions: 29 | - 17.0.0 30 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: ["*"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | strategy: 14 | matrix: 15 | node-version: [10.x, 12.x, 14.x] 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: npm install 24 | - run: git submodule update --init 25 | - run: npm test 26 | - name: Coveralls 27 | uses: coverallsapp/github-action@master 28 | with: 29 | github-token: ${{ secrets.GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | publish-npm: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - uses: actions/setup-node@v1 13 | with: 14 | node-version: 14 15 | registry-url: https://registry.npmjs.org/ 16 | - run: npm install 17 | - run: git submodule update --init 18 | - run: npm test 19 | - name: Publish beta version to npm 20 | if: "github.event.release.prerelease" 21 | run: npm publish --tag beta 22 | env: 23 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 24 | - name: Publish to npm 25 | if: "!github.event.release.prerelease" 26 | run: npm publish 27 | env: 28 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | .nyc_output 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | .DS_Store 31 | 32 | # Compiled templates 33 | localize/**/*.js 34 | localize/**/*.d.ts 35 | !localize/types.d.ts 36 | 37 | # Browserified tests 38 | .browser 39 | 40 | # bundles 41 | dist/ 42 | 43 | # IDE files 44 | .idea 45 | 46 | package-lock.json 47 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "spec/JSON-Schema-Test-Suite"] 2 | path = spec/JSON-Schema-Test-Suite 3 | url = https://github.com/json-schema/JSON-Schema-Test-Suite.git 4 | [submodule "spec/json-typedef-spec"] 5 | path = spec/json-typedef-spec 6 | url = https://github.com/jsontypedef/json-typedef-spec.git 7 | [submodule "spec/ajv-keywords"] 8 | path = spec/ajv-keywords 9 | url = https://github.com/ajv-validator/ajv-keywords.git 10 | [submodule "spec/ajv-formats"] 11 | path = spec/ajv-formats 12 | url = https://github.com/ajv-validator/ajv-formats 13 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | spec/JSON-Schema-Test-Suite 2 | spec/json-typedef-spec 3 | spec/ajv-keywords 4 | spec/ajv-formats 5 | .browser 6 | coverage 7 | bundle 8 | .nyc_output 9 | localize -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at ajv.validator@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Evgeny Poberezkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ajv-i18n 2 | 3 | Internationalised error messages for [Ajv](https://github.com/ajv-validator/ajv) - superfast JSON validator for JSON Schema and JSON Type Definition. 4 | 5 | [![Build Status](https://travis-ci.org/ajv-validator/ajv-i18n.svg?branch=master)](https://travis-ci.org/ajv-validator/ajv-i18n) 6 | [![npm](https://img.shields.io/npm/v/ajv-i18n.svg)](https://www.npmjs.com/package/ajv-i18n) 7 | [![Coverage Status](https://coveralls.io/repos/github/ajv-validator/ajv-i18n/badge.svg?branch=master)](https://coveralls.io/github/ajv-validator/ajv-i18n?branch=master) 8 | [![Gitter](https://img.shields.io/gitter/room/ajv-validator/ajv.svg)](https://gitter.im/ajv-validator/ajv) 9 | 10 | ## Supported locales 11 | 12 | |locale|language |contributor|draft-04|draft-061|draft-072|draft
2019-093
/2020-124|JTD5 13 | |------|:-------:|:---------:|:------:|:------:|:------:|:------:|:------:| 14 | |🇬🇧 en|English | |✓|✓|✓|✓|✓| 15 | |AR ar|Arabic |[Mahmoud-Mardeni](https://github.com/Mahmoud-Mardeni)|✓|✓|✓|-|-| 16 | |CA ca|Catalan |[alexandreec](https://github.com/alexandreec)|✓|✓|✓|-|*| 17 | |🇨🇿 cs|Czech |[kiskovacs](https://github.com/kiskovacs)
[NAM0007](https://github.com/NAM0007)|✓
 |✓
 |
✓|-|*| 18 | |🇩🇪 de|German |[jmtoball](https://github.com/jmtoball)
[gflohr](https://github.com/gflohr)|✓
 |✓
 |
✓|✓
 |✓
 | 19 | |🇪🇸 es|Spanish |[jpablom](https://github.com/jpablom)|✓|✓|✓|-|*| 20 | |🇫🇮 fi|Finnish |[saulipurhonen](https://github.com/saulipurhonen)|✓|✓|✓|✓|✓| 21 | |🇫🇷 fr|French |[monlouisj](https://github.com/monlouisj)
[Telokis](https://github.com/Telokis)|✓
 |✓
 |
✓|-|*| 22 | |🇭🇺 hu|Hungarian|[szilveszter9](https://github.com/szilveszter9)|✓|-|-|-|*| 23 | |🇮🇩 id|Indonesian|[ekoeryanto](https://github.com/ekoeryanto)|✓|✓|✓|-|*| 24 | |🇮🇹 it|Italian |[jasoniangreen](https://github.com/jasoniangreen)
[lucacorti](https://github.com/lucacorti)|✓
 |
✓|
✓|
✓|
✓| 25 | |🇯🇵 ja|Japanese |[gilgongo](https://github.com/gilgongo)|✓|-|-|-|*| 26 | |🇰🇷 ko|Korean |[MinByeongDon](https://github.com/MinByeongDon)|✓|✓|✓|✓|✓| 27 | |🇳🇴 nb|Norwegian bokmål|[mtramm](https://github.com/mtramm)|✓|✓|-|-|*| 28 | |🇳🇱 nl|Dutch |[pimlie](https://github.com/pimlie)
[niekvb](https://github.com/niekvb)|✓|✓|✓|
✓|
✓| 29 | |🇵🇱 pl|Polish |[danielzurawski](https://github.com/danielzurawski)|✓|-|-|-|*| 30 | |🇧🇷 pt-BR|Português - Brasil|[marcosrava](https://github.com/marcosrava)
[ggondim](https://github.com/ggondim)|✓|✓|✓|
✓|
✓| 31 | |🇷🇺 ru|Russian | |✓|✓|✓|✓|✓| 32 | |🇸🇰 sk|Slovak |[kiskovacs](https://github.com/kiskovacs)|✓|✓|-|-|*| 33 | |🇸🇪 sv|Swedish |[limmen](https://github.com/Limmen)|✓|✓|-|-|*| 34 | |🇹🇭 th|Thai |[encX](https://github.com/encX)|✓|✓|✓|✓|✓| 35 | |🇨🇳 zh|Chinese |[jinzhubaofu](https://github.com/jinzhubaofu)
[leuction](https://github.com/leuction)|✓
 |
✓|
✓|
✓|
✓| 36 | |🇹🇼 zh-TW|Chinese - Taiwan|[minipai](https://github.com/minipai)|✓|✓|✓|✓|✓| 37 | 38 | 39 | 1 added boolean schema, keywords `const`, `contains`, `propertyNames` 40 | 41 | 2 added keywords `if`/`then`/`else` 42 | 43 | 3 added messages for keywords `unevaluatedProperties`, `unevaluatedItems`, `dependentRequired` 44 | 45 | 4 keyword `items` messages 46 | 47 | 5 JSON Type Definition 48 | 49 | \* `discriminator` form messages are not translated 50 | 51 | Please contribute locales that you need to use if they are missing or incomplete. 52 | 53 | ## Install 54 | 55 | Using npm: 56 | 57 | ``` 58 | npm install ajv-i18n 59 | ``` 60 | 61 | ## Usage 62 | 63 | In node: 64 | 65 | ```javascript 66 | const Ajv = require("ajv") // version >= 8.0.0 67 | const localize = require("ajv-i18n") 68 | // or for JSON Type Definition 69 | // const localize = require("ajv-i18n/localize/jtd") 70 | 71 | const ajv = Ajv({allErrors: true, messages: false}) 72 | const validate = ajv.compile(schema) 73 | const valid = validate(data) 74 | 75 | if (!valid) { 76 | // ru for Russian 77 | localize.ru(validate.errors) 78 | // string with all errors and data paths 79 | console.log(ajv.errorsText(validate.errors, {separator: '\n'})) 80 | } 81 | ``` 82 | 83 | To require only necessary locales (e.g., with browserify): 84 | 85 | ```javascript 86 | const localize_ru = require('ajv-i18n/localize/ru') 87 | // or for JSON Type Definition 88 | // const localize_ru = require('ajv-i18n/localize/ru/jtd') 89 | ``` 90 | 91 | or 92 | 93 | ```javascript 94 | const localize = { 95 | en: require('ajv-i18n/localize/en'), 96 | ru: require('ajv-i18n/localize/ru'), 97 | } 98 | ``` 99 | 100 | See [Ajv docs](https://github.com/ajv-validator/ajv) for more information. 101 | 102 | ## Tests 103 | 104 | ``` 105 | npm install 106 | git submodule update --init 107 | npm test 108 | ``` 109 | 110 | ## Contributing 111 | 112 | Functions that localize error messages are generated using doT template [localize.jst](https://github.com/ajv-validator/ajv-i18n/tree/master/localize/localize.jst), [JSON Schema messages](https://github.com/ajv-validator/ajv-i18n/tree/master/messages/index.js) and [JSON Type Definition messages](https://github.com/ajv-validator/ajv-i18n/tree/master/messages/jtd.js). Templates are pre-compiled, so doT is not a run-time dependency. 113 | 114 | `npm run build` - compiles functions to [localize](https://github.com/ajv-validator/ajv/tree/master/localize) folder. 115 | 116 | ## Contributors of locales 117 | 118 | [![danielzurawski](https://avatars3.githubusercontent.com/u/1625711?v=3&s=40)](https://github.com/danielzurawski "danielzurawski") 119 | [![szilveszter9](https://avatars0.githubusercontent.com/u/7540866?v=3&s=40)](https://github.com/szilveszter9 "szilveszter9") 120 | [![jmtoball](https://avatars0.githubusercontent.com/u/219950?v=3&s=40)](https://github.com/jmtoball "jmtoball") 121 | [![gilgongo](https://avatars2.githubusercontent.com/u/4561747?v=3&s=40)](https://github.com/gilgongo "gilgongo") 122 | [![jasoniangreen](https://avatars3.githubusercontent.com/u/3481367?v=3&s=40)](https://github.com/jasoniangreen "jasoniangreen") 123 | [![jpablom](https://avatars0.githubusercontent.com/u/3935083?v=3&s=40)](https://github.com/jpablom "jpablom") 124 | [![limmen](https://avatars2.githubusercontent.com/u/8254791?v=3&s=40)](https://github.com/Limmen "Limmen") 125 | [![jinzhubaofu](https://avatars2.githubusercontent.com/u/811195?v=3&s=40)](https://github.com/jinzhubaofu "jinzhubaofu") 126 | [![kiskovacs](https://avatars1.githubusercontent.com/u/2733311?v=3&s=40)](https://github.com/kiskovacs "kiskovacs") 127 | [![mahmoud-mardeni](https://avatars2.githubusercontent.com/u/19661270?s=40&v=3)](https://github.com/Mahmoud-Mardeni "mahmoud-mardeni") 128 | [![monlouisj](https://avatars0.githubusercontent.com/u/5998380?v=3&s=40)](https://github.com/monlouisj "monlouisj") 129 | [![marcosrava](https://avatars2.githubusercontent.com/u/243790?v=3&s=40)](https://github.com/marcosrava "marcosrava") 130 | [![mtramm](https://avatars3.githubusercontent.com/u/3519541?v=3&s=40)](https://github.com/mtramm "mtramm") 131 | [![Mahmoud-Mardeni](https://avatars3.githubusercontent.com/u/19661270?v=3&s=40)](https://github.com/Mahmoud-Mardeni "Mahmoud-Mardeni") 132 | [![leuction](https://avatars3.githubusercontent.com/u/8056270?v=3&s=40)](https://github.com/leuction "leuction") 133 | [![lucacorti](https://avatars2.githubusercontent.com/u/1076999?v=3&s=40)](https://github.com/lucacorti "lucacorti") 134 | [![minipai](https://avatars2.githubusercontent.com/u/239570?s=40&v=4)](https://github.com/minipai "minipai") 135 | [![encX](https://avatars3.githubusercontent.com/u/5965883?v=3&s=40)](https://github.com/encX "encX") 136 | [pimlie](https://github.com/pimlie "pimlie") 137 | [![MinByeongDon](https://avatars2.githubusercontent.com/u/6141807?s=40&v=4)](https://github.com/MinByeongDon "MinByeongDon") 138 | [![gflohr](https://avatars0.githubusercontent.com/u/7126580?s=40&v=4)](https://github.com/gflohr "gflohr") 139 | [![ekoeryanto](https://avatars2.githubusercontent.com/u/36023898?s=40&v=4)](https://github.com/ekoeryanto "ekoeryanto") 140 | [![Telokis](https://avatars3.githubusercontent.com/u/6382729?s=40&v=4)](https://github.com/Telokis "Telokis") 141 | [alexandreec](https://github.com/alexandreec "alexandreec") 142 | [![ggondim](https://avatars2.githubusercontent.com/u/2074685?s=40&v=4)](https://github.com/ggondim "ggondim") 143 | [![niekvb](https://avatars3.githubusercontent.com/u/37668320?s=40&v=4)](https://github.com/niekvb "niekvb") 144 | [![NAM0007](https://avatars1.githubusercontent.com/u/47188486?s=40&v=4)](https://github.com/NAM0007 "NAM0007") 145 | [![saulipurhonen](https://avatars.githubusercontent.com/u/48789543?s=40&v=4)](https://github.com/saulipurhonen "saulipurhonen") 146 | 147 | ## Enterprise support 148 | 149 | ajv-i18n package is a part of [Tidelift enterprise subscription](https://tidelift.com/subscription/pkg/npm-ajv-i18n?utm_source=npm-ajv-i18n&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers. 150 | 151 | ## Security contact 152 | 153 | To report a security vulnerability, please use the 154 | [Tidelift security contact](https://tidelift.com/security). 155 | Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerability via GitHub issues. 156 | 157 | ## License 158 | 159 | [MIT](https://github.com/ajv-validator/ajv-i18n/blob/master/LICENSE) 160 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | // Generated on Fri Feb 26 2016 16:59:16 GMT+0900 (JST) 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | // base path that will be used to resolve all patterns (eg. files, exclude) 7 | basePath: "", 8 | 9 | // frameworks to use 10 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 11 | frameworks: ["mocha"], 12 | 13 | // list of files / patterns to load in the browser 14 | files: ["dist/ajv-i18n.test.min.js", ".browser/*.spec.js"], 15 | 16 | // test results reporter to use 17 | // possible values: 'dots', 'progress' 18 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 19 | reporters: ["dots"], 20 | 21 | // web server port 22 | port: 9876, 23 | 24 | // enable / disable colors in the output (reporters and logs) 25 | colors: true, 26 | 27 | // level of logging 28 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 29 | logLevel: config.LOG_INFO, 30 | 31 | // enable / disable watching file and executing tests whenever any file changes 32 | autoWatch: false, 33 | 34 | // start these browsers 35 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 36 | browsers: ["Chrome"], 37 | 38 | // Continuous Integration mode 39 | // if true, Karma captures browsers, runs the tests and exits 40 | singleRun: true, 41 | 42 | browserNoActivityTimeout: 90000, 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /localize/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | no-redeclare: 0 -------------------------------------------------------------------------------- /localize/README.md: -------------------------------------------------------------------------------- 1 | This folder contains compiled localization functions. 2 | 3 | Do not edit `*.js` files directly, edit JSON Schema messages in [messages/index.js](https://github.com/epoberezkin/ajv-i18n/tree/master/messages/index.js) and JSON Type Definition messages in [messages/jtd.js](https://github.com/epoberezkin/ajv-i18n/tree/master/messages/jtd.js). 4 | 5 | If this folder doesn't have any locale sub-folders, run `npm run build`. 6 | -------------------------------------------------------------------------------- /localize/index.d.jst: -------------------------------------------------------------------------------- 1 | import {Localize} from "./types"; 2 | 3 | type Language = 4 | {{~ it.locales:locale }} 5 | | "{{=locale}}" 6 | {{~}}; 7 | 8 | declare const def: Record; 9 | export default def; 10 | -------------------------------------------------------------------------------- /localize/index.jst: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | {{ 4 | const IDENT = /^[a-z_$][a-z0-9_$]*$/i; 5 | }} 6 | 7 | module.exports = { 8 | {{~ it.locales:locale }} 9 | {{? IDENT.test(locale) }} 10 | {{=locale}}: 11 | {{??}} 12 | "{{=locale}}": 13 | {{?}} 14 | require("./{{=locale}}{{=it.importFile}}"), 15 | {{~}} 16 | }; 17 | -------------------------------------------------------------------------------- /localize/localize.d.jst: -------------------------------------------------------------------------------- 1 | import {Localize} from "../types"; 2 | declare const localize: Localize; 3 | export default localize; 4 | -------------------------------------------------------------------------------- /localize/localize.jst: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | {{ 4 | const STRIP_FUNCTION = /function\s+anonymous\s*\(it[^)]*\)\s*{|return\s+out;\s*}/g; 5 | const VAR_OUT = /var\s+out/; 6 | const OUT_EMPTY_STRING = /out\s*\+=\s*\'\'\s*\+\s*/g; 7 | }} 8 | 9 | {{ var name = 'localize_' + it.locale.replace('-','_'); }} 10 | module.exports = function {{=name}}(errors) { 11 | if (!(errors && errors.length)) return; 12 | for (const e of errors) { 13 | let out; 14 | switch (e.keyword) { 15 | {{~ it.messages:msg }} 16 | case "{{= msg.keyword }}": 17 | {{~ msg.keywords:kwd }} 18 | case '{{= kwd }}': 19 | {{~}} 20 | {{? typeof msg.msgFunc == "function" }} 21 | {{= stripFunction(msg.msgFunc) }} 22 | {{?? msg.msgFunc.length }} 23 | switch (e.params.error) { 24 | {{~ msg.msgFunc:err }} 25 | case "{{= err.error }}": 26 | {{= stripFunction(err.func) }} 27 | break; 28 | {{~}} 29 | default: 30 | {{? it.typeMessage }} 31 | {{= stripFunction(it.typeMessage) }} 32 | {{??}} 33 | {{= stripFunction(it.defaultMessage) }} 34 | {{?}} 35 | } 36 | {{??}} 37 | {{= stripFunction(it.typeMessage) }} 38 | {{?}} 39 | break; 40 | {{~}} 41 | default: 42 | {{= stripFunction(it.defaultMessage) }} 43 | } 44 | e.message = out; 45 | } 46 | }; 47 | 48 | {{ 49 | function stripFunction(code) { 50 | return code.toString() 51 | .replace(STRIP_FUNCTION, '') 52 | .replace(VAR_OUT, 'out') 53 | .replace(OUT_EMPTY_STRING, 'out += '); 54 | } 55 | }} 56 | -------------------------------------------------------------------------------- /localize/types.d.ts: -------------------------------------------------------------------------------- 1 | import {ErrorObject} from "ajv" 2 | 3 | export interface Localize { 4 | (errors?: null | ErrorObject[]): void 5 | } 6 | -------------------------------------------------------------------------------- /messages/index.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | /** 4 | * When adding new locales, please maintain alphabetic ordering. 5 | * "en" must remain in the first position. 6 | * Tests will fail otherwise. 7 | */ 8 | 9 | module.exports = { 10 | // supported locales 11 | _locales: [ 12 | "en", 13 | "ar", 14 | "ca", 15 | "cs", 16 | "de", 17 | "es", 18 | "fi", 19 | "fr", 20 | "hu", 21 | "id", 22 | "it", 23 | "ja", 24 | "ko", 25 | "nb", 26 | "nl", 27 | "pl", 28 | "pt-BR", 29 | "ru", 30 | "sk", 31 | "sv", 32 | "th", 33 | "zh", 34 | "zh-TW", 35 | ], 36 | 37 | // shared defines 38 | _defs: { 39 | n: "{{var n = e.params.limit;}}", 40 | mPlural: { 41 | // plural for the words item (element) and character 42 | en: "{{? n!=1 }}s{{?}}", 43 | ar: "{{? n!=1 }}عناصر{{?}}", 44 | ca: "{{? n!=1 }}s{{?}}", 45 | cs: "{{? n>=2 && n<=4 }}ky{{?? n!=1 }}ek{{??}}ků{{?}}", 46 | de: "{{? n!=1 }}e{{?}}", 47 | es: "{{? n!=1 }}s{{?}}", //only item (element) 48 | fr: "{{? n!=1 }}s{{?}}", 49 | it: "{{? n==1 }}o{{??}}i{{?}}", 50 | nb: "{{? n!=1 }}er{{?}}", 51 | nl: "{{? n!=1 }}s{{?}}", 52 | pl: "{{? n==1 }}u{{??}}ów{{?}}", 53 | "pt-BR": "{{? n!=1 }}s{{?}}", 54 | ru: "{{? n>=2 && n<=4 }}а{{?? n!=1 }}ов{{?}}", 55 | sk: "{{? n==1 }}ok{{??}}kov{{?}}", 56 | sv: "{{? n!=1 }}er{{?}}", 57 | }, 58 | propPlural: { 59 | // plural for the word property (attribute) 60 | en: "{{? n==1 }}y{{??}}ies{{?}}", 61 | ar: "{{? n!=1 }}خصائص{{?}}", 62 | ca: "{{? n!=1 }}s{{?}}", 63 | cs: "{{? n>=2 && n<=4 }}ky{{?? n!=1 }}ek{{??}}ka{{?}}", 64 | de: "{{? n!=1 }}e{{?}}", 65 | es: "{{? n!=1 }}es{{?}}", 66 | fr: "{{? n!=1 }}s{{?}}", 67 | hu: "{{? n!=1 }}i{{?}}", 68 | it: "{{? n==1 }}o{{??}}i{{?}}", 69 | nb: "{{? n==1 }}en{{??}}er{{?}}", 70 | nl: "{{? n!=1 }}pen{{?}}", 71 | pl: "{{? n==1 }}e{{??}}a{{?}}", 72 | "pt-BR": "{{? n!=1 }}s{{?}}", 73 | ru: "{{? n==1 }}е{{?? n>=2 && n<=4 }}я{{??}}ей{{?}}", 74 | sk: "{{? n>=2 && n<=4 }}ky{{?? n!=1 }}iek{{??}}ka{{?}}", 75 | sv: "{{? n!=1 }}er{{?}}", 76 | }, 77 | }, 78 | 79 | // error messages 80 | _defaultMessage: { 81 | en: 'must pass "{{=e.keyword}}" keyword validation', 82 | ar: 'يجب أن تمرر كلمة التحقق المفتاحية "{{=e.keyword}}"', 83 | ca: 'ha de passar la validació de la clau "{{=e.keyword}}"', 84 | cs: 'musí vyhovět "{{=e.keyword}}" validaci', 85 | de: 'muss die Validierung "{{=e.keyword}}" bestehen', 86 | es: 'debe pasar la validación de palabra clave "{{=e.keyword}}"', 87 | fi: 'täytyy läpäistä "{{=e.keyword}}" avainsanatarkistus', 88 | fr: 'doit être valide selon le critère "{{=e.keyword}}"', 89 | id: 'harus lulus validasi kata kunci "{{=e.keyword}}"', 90 | it: 'deve essere valido secondo il criterio "{{=e.keyword}}"', 91 | ko: '"{{=e.keyword}}"키워드 검사를 통과해야 합니다', 92 | nb: "må samsvare med valideringen for {{=e.keyword}}", 93 | nl: 'moet sleutelwoord validatie "{{=e.keyword}}" doorstaan', 94 | pl: 'powinien przejść walidację "{{=e.keyword}}"', 95 | "pt-BR": 'deve passar a validação da keyword "{{=e.keyword}}"', 96 | ru: 'должно соответствовать правилу "{{=e.keyword}}"', 97 | sk: 'musí splniť "{{=e.keyword}}" validáciu', 98 | sv: 'bör passera "{{=e.keyword}}" nyckelord validering', 99 | th: 'ต้องผ่านคีย์เวิร์ด "{{=e.keyword}}"', 100 | zh: '应当通过 "{{=e.keyword}} 关键词校验"', 101 | "zh-TW": '應該通過 "{{=e.keyword}} 關鍵詞檢驗"', 102 | }, 103 | 104 | "false schema": { 105 | en: "boolean schema is false", 106 | ar: "المخطط المنطقي غير صحيح", 107 | ca: "l’esquema és fals", 108 | cs: "schéma je false", 109 | de: "boolesches Schema ist falsch", 110 | es: "el esquema és falso", 111 | fi: "boolean skeema on väärä", 112 | fr: 'le schema est "false"', 113 | id: "skema boolean salah", 114 | it: "lo schema booleano è falso", 115 | ko: "boolean 스키마는 올바르지 않습니다", 116 | nb: "boolsk schema er usannt", 117 | nl: "boolean schema is fout", 118 | "pt-BR": 'o schema booleano é "false"', 119 | ru: "схема равна false", 120 | sk: "schéma je false", 121 | sv: "boolean schema är falskt", 122 | th: "schema เป็น false", 123 | zh: "布尔模式出错", 124 | "zh-TW": "布林模式不正確", 125 | }, 126 | additionalItems: { 127 | _keywords: ["items"], // for JSON Schema draft-2020-12 128 | en: "{{#def.n}}must NOT have more than {{=n}} item{{#def.mPlural}}", 129 | ar: "{{#def.n}} يجب أن لا يحوي أكثر من {{=n}} عنصر", 130 | ca: "{{#def.n}}no ha de tenir més de {{=n}} element{{#def.mPlural}}", 131 | cs: "{{#def.n}}nemůže mít víc, než {{=n}} prv{{#def.mPlural}}", 132 | de: "{{#def.n}}darf nicht mehr als {{=n}} Element{{#def.mPlural}} enthalten", 133 | es: "{{#def.n}}no debe tener más de {{=n}} elemento{{#def.mPlural}}", 134 | fi: "{{#def.n}}saa sisältää enintään {{=n}}{{? n==1 }}:n elementin{{??}} elementtiä{{?}}", 135 | fr: "{{#def.n}}ne doit pas contenir plus de {{=n}} élémént{{#def.mPlural}}", 136 | hu: "{{#def.n}}nem lehet több, mint {{=n}} eleme", 137 | id: "{{#def.n}} tidak boleh memiliki lebih dari {{=n}} item", 138 | it: "{{#def.n}}non dovrebbe avere più di {{=n}} element{{#def.mPlural}}", 139 | ja: "{{#def.n}}は{{=n}}以上あってはいけない", 140 | ko: "{{#def.n}} 항목은 아이템을 {{=n}}개 이상 가질 수 없습니다", 141 | nb: "{{#def.n}}kan ikke ha mer enn {{=n}} element{{#def.mPlural}}", 142 | nl: "{{#def.n}}mag niet meer dan {{=n}} item{{#def.mPlural}} bevatten", 143 | pl: "{{#def.n}}nie powinien mieć więcej niż {{=n}} element{{#def.mPlural}}", 144 | "pt-BR": "não são permitidos itens adicionais (mais do que {{=n}})", 145 | ru: "{{#def.n}}должно иметь не более, чем {{=n}} элемент{{#def.mPlural}}", 146 | sk: "{{#def.n}}nemôže obsahovať viac, než {{=n}} prv{{#def.mPlural}}", 147 | sv: "{{#def.n}}borde ha fler än {{=n}} sak{{#def.mPlural}}", 148 | th: "{{#def.n}}ต้องมีสมาชิกไม่เกิน {{=n}} ตัว", 149 | zh: "{{#def.n}}不允许超过{{=n}}个元素", 150 | "zh-TW": "{{#def.n}}不可以超過{{=n}}個元素", 151 | }, 152 | additionalProperties: { 153 | en: "must NOT have additional properties", 154 | ar: "يجب أن لا يحوي خصائص إضافية", 155 | ca: "no ha de tenir propietats addicionals", 156 | cs: "nemůže mít další položky", 157 | de: "darf keine zusätzlichen Attribute haben", 158 | es: "no debe tener propiedades adicionales", 159 | fi: "ei saa sisältää ylimääräisiä ominaisuuksia", 160 | fr: "ne doit pas contenir de propriétés additionnelles", 161 | hu: "nem lehetnek további elemei", 162 | id: "tidak boleh memiliki properti tambahan", 163 | it: "non deve avere attributi aggiuntivi", 164 | ja: "追加してはいけない", 165 | ko: "추가적인 속성은 허용되지 않습니다", 166 | nb: "kan ikke ha flere egenskaper", 167 | nl: "mag geen extra eigenschappen bevatten", 168 | pl: "nie powinien zawierać dodatkowych pól", 169 | "pt-BR": "não são permitidas propriedades adicionais", 170 | ru: "не должно иметь дополнительных полей", 171 | sk: "nemôže obsahovať ďalšie položky", 172 | sv: "borde inte ha fler egenskaper", 173 | th: "ต้องไม่มี property อื่นๆ นอกเหนีอจากที่กำหนดไว้", 174 | zh: "不允许有额外的属性", 175 | "zh-TW": "不可以有額外的屬性", 176 | }, 177 | anyOf: { 178 | en: 'must match a schema in "anyOf"', 179 | ar: 'يجب أن يوافق أحد المخططات الموجودة في "anyOf"', 180 | ca: 'ha de coincidir amb algun esquema definit a "anyOf"', 181 | cs: 'musí vyhovět alespoň jednomu schématu v "anyOf"', 182 | de: 'muss einem der Schemata in "anyOf" entsprechen', 183 | es: 'debe coincidir con algún esquema en "anyOf"', 184 | fi: 'täytyy vastata "anyOf" skeemaa', 185 | fr: 'doit correspondre à un schéma de "anyOf"', 186 | hu: 'meg kell feleljen legalább egy "anyOf" alaknak', 187 | id: 'harus cocok dengan beberapa skema pada "anyOf"', 188 | it: 'deve corrispondere ad uno degli schema in "anyOf"', 189 | ja: '"anyOf"のスキーマとマッチしなくてはいけない', 190 | ko: '"anyOf"의 스키마와 일치해야 합니다', 191 | nb: 'må samsvare med et schema i "anyOf"', 192 | nl: 'moet overeenkomen met een schema in "anyOf"', 193 | pl: 'powinien pasować do wzoru z sekcji "anyOf"', 194 | "pt-BR": 'os dados não correspondem a nenhum schema de "anyOf"', 195 | ru: 'должно соответствовать одной их схем в "anyOf"', 196 | sk: 'musí splňovať aspoň jednu zo schém v "anyOf"', 197 | sv: 'borde matcha något schema i "anyOf"', 198 | th: 'ต้องตรงกับหนึ่งใน schema ที่กำหนดไว้ใน "anyOf"', 199 | zh: "数据应为 anyOf 所指定的其中一个", 200 | "zh-TW": "不符合 anyOf 指定的模式", 201 | }, 202 | dependencies: { 203 | _keywords: ["dependentRequired"], 204 | _defs: { 205 | n: "{{var n = e.params.depsCount;}}", 206 | }, 207 | en: "{{#def.n}}must have propert{{#def.propPlural}} {{=e.params.deps}} when property {{=e.params.property}} is present", 208 | ar: "{{#def.n}} يجب أن يحوي الخصائص {{=e.params.deps}} عندما تكون الخاصية {{=e.params.property}} موجودة", 209 | ca: "{{#def.n}}ha de contenir la propietat{{#def.propPlural}} {{=e.params.deps}} quan la propietat {{=e.params.property}} és present", 210 | cs: "{{#def.n}}musí mít polož{{#def.propPlural}}: {{=e.params.deps}}, pokud obsahuje {{=e.params.property}}", 211 | de: "{{#def.n}}muss Attribut{{#def.propPlural}} {{=e.params.deps}} aufweisen, wenn Attribut {{=e.params.property}} gesetzt ist", 212 | es: "{{#def.n}}debe contener la{{#def.mPlural}} propiedad{{#def.propPlural}} {{=e.params.deps}} cuando la propiedad {{=e.params.property}} se encuentra presente", 213 | fi: "{{#def.n}}täytyy sisältää {{=e.params.deps}} ominaisuu{{? n==1 }}s{{??}}det{{?}} kun {{=e.params.property}}-ominaisuus on läsnä", 214 | fr: "{{#def.n}}doit avoir la propriété {{=e.params.deps}} quand la propriété {{=e.params.property}} est présente", 215 | hu: "{{#def.n}}-nak kell legyen{{? n>1 }}ek{{?}} a következő tulajdonsága{{#def.propPlural}}: {{=e.params.deps}}, ha van {{=e.params.property}} tulajdonsága", 216 | id: "{{#def.n}} harus memiliki properti {{=e.params.deps}} ketika properti {{=e.params.property}} hadir", 217 | it: "{{#def.n}}dovrebbe avere {{? n==1 }}l'{{??}}gli {{?}}attribut{{#def.propPlural}} {{=e.params.deps}} quando l'attributo {{=e.params.property}} è presente", 218 | ja: "{{=e.params.property}}がある場合、{{#def.n}}は{{=e.params.deps}}をつけなければいけない", 219 | ko: "{{#def.n}}{{=e.params.property}}속성이 있는 경우, {{=e.params.deps}} 속성이 있어야합니다", 220 | nb: "{{#def.n}}må ha egenskapen{{? n != 1}}e{{?}} {{=e.params.deps}} når egenskapen {{=e.params.property}} er angitt", 221 | nl: "{{#def.n}}moet de eigenschap{{#def.propPlural}} {{=e.params.deps}} bevatten als {{=e.params.property}} is gedefinieerd", 222 | pl: "{{#def.n}}powinien zawierać pol{{#def.propPlural}} {{=e.params.deps}} kiedy pole {{=e.params.property}} jest obecne", 223 | "pt-BR": 224 | "{{#def.n}} deve ter propriedade{{#def.propPlural}} {{=e.params.deps}} quando a propriedade {{=e.params.property}} estiver presente", 225 | ru: "{{#def.n}}должно иметь пол{{? n==1 }}е{{??}}я{{?}} {{=e.params.deps}}, когда присутствует поле {{=e.params.property}}", 226 | sk: "{{#def.n}} musí obsahovať polož{{#def.propPlural}}: {{=e.params.deps}}, ak obsahuje {{=e.params.property}}", 227 | sv: "{{#def.n}}borde ha egenskap{{#def.propPlural}} {{=e.params.deps}} när egenskap {{=e.params.property}} finns tillgängligt", 228 | th: "{{#def.n}}เมื่อมี property {{=e.params.property}} แล้วจะต้องมี property {{=e.params.deps}} ด้วย", 229 | zh: "{{#def.n}}应当拥有属性{{=e.params.property}}的依赖属性{{=e.params.deps}}", 230 | "zh-TW": "{{#def.n}}應該要有屬性{{=e.params.property}}的依賴屬性{{=e.params.deps}}", 231 | }, 232 | enum: { 233 | en: "must be equal to one of the allowed values", 234 | ar: "قيمة هذا الحقل يجب أن تكون مساوية لأحد القيم المعرفة مسبقاً", 235 | ca: "ha de ser igual a un dels valors predefinits", 236 | cs: "musí být rovno jedné hodnotě z výčtu", 237 | de: "muss einem der vorgegebenen Werte entsprechen", 238 | es: "deber ser igual a uno de los valores predefinidos", 239 | fi: "täytyy olla yhtä kuin jokin sallituista arvoista", 240 | fr: "doit être égal à une des valeurs prédéfinies", 241 | hu: "egyenlő kell legyen valamely előre meghatározott értékkel", 242 | id: "harus sama dengan salah satu dari nilai yang telah ditentukan", 243 | it: "deve essere uguale ad uno dei valori consentiti", 244 | ja: "事前に定義された値のいずれかに等しくなければいけない", 245 | ko: "미리 정의된 값중 하나여야 합니다", 246 | nb: "må være lik en av de forhåndsdefinerte verdiene", 247 | nl: "moet overeenkomen met één van de voorgedefinieerde waarden", 248 | pl: "powinien być równy jednej z predefiniowanych wartości", 249 | "pt-BR": "deve ser igual a um dos valores permitidos", 250 | ru: "должно быть равно одному из разрешенных значений", 251 | sk: "musí byť jedna z definovaných hodnôt", 252 | sv: "borde vara ekvivalent med en av dess fördefinierade värden", 253 | th: "ต้องตรงกับหนึ่งในค่าที่กำหนดไว้", 254 | zh: "应当是预设定的枚举值之一", 255 | "zh-TW": "應該要在預設的值之中", 256 | }, 257 | format: { 258 | en: 'must match format "{{=e.params.format}}"', 259 | ar: 'يجب أن يوافق الصيغة "{{=e.params.format}}"', 260 | ca: 'ha de coincidir amb el format "{{=e.params.format}}"', 261 | cs: 'musí být ve formátu "{{=e.params.format}}"', 262 | de: 'muss diesem Format entsprechen: "{{=e.params.format}}"', 263 | es: 'debe coincidir con el formato "{{=e.params.format}}"', 264 | fi: 'täytyy vastata muotoa "{{=e.params.format}}"', 265 | fr: 'doit correspondre au format "{{=e.params.format}}"', 266 | hu: 'meg kell feleljen a következő formátumnak: "{{=e.params.format}}"', 267 | id: 'harus cocok dengan format "{{=e.params.format}}"', 268 | it: 'deve corrispondere al formato "{{=e.params.format}}"', 269 | ja: '"{{=e.params.format}}"形式に揃えなければいけない', 270 | ko: '"{{=e.params.format}}" 포맷과 일치해야 합니다', 271 | nb: 'må stemme overens med formatet "{{=e.params.format}}"', 272 | nl: 'moet overeenkomen met het volgende formaat: "{{=e.params.format}}"', 273 | pl: 'powinien zgadzać się z formatem "{{=e.params.format}}"', 274 | "pt-BR": 'deve corresponder ao formato "{{=e.params.format}}"', 275 | ru: 'должно соответствовать формату "{{=e.params.format}}"', 276 | sk: 'musí obsahovať formát "{{=e.params.format}}"', 277 | sv: 'borde matcha formatet "{{=e.params.format}}"', 278 | th: 'ต้องเป็นรูปแบบ "{{=e.params.format}}"', 279 | zh: '应当匹配格式 "{{=e.params.format}}"', 280 | "zh-TW": "應該要符合{{=e.params.format}}格式", 281 | }, 282 | maximum: { 283 | _keywords: ["exclusiveMaximum"], 284 | _defs: { 285 | c: '{{var cond = e.params.comparison + " " + e.params.limit;}}', 286 | }, 287 | en: "{{#def.c}}must be {{=cond}}", 288 | ar: "{{#def.c}} يجب أن يكون {{=cond}}", 289 | ca: "{{#def.c}}ha de ser {{=cond}}", 290 | cs: "{{#def.c}}musí být {{=cond}}", 291 | de: "{{#def.c}}muss {{=cond}} sein", 292 | es: "{{#def.c}}debe ser {{=cond}}", 293 | fi: "{{#def.c}}täytyy olla {{=cond}}", 294 | fr: "{{#def.c}}doit être {{=cond}}", 295 | hu: "{{#def.c}}kell legyen {{=cond}}", 296 | id: "{{#def.c}}harus {{=cond}}", 297 | it: "{{#def.c}}deve essere {{=cond}}", 298 | ja: "{{#def.c}}{{=cond}}でなければいけない", 299 | ko: "{{#def.c}} {{=cond}} 이여야 합니다", 300 | nb: "{{#def.c}}må være {{=cond}}", 301 | nl: "{{#def.c}}moet {{=cond}} zijn", 302 | pl: "{{#def.c}}powinien być {{=cond}}", 303 | "pt-BR": "{{#def.c}}deve ser {{=cond}}", 304 | ru: "{{#def.c}}должно быть {{=cond}}", 305 | sk: "{{#def.c}}musí byť {{=cond}}", 306 | sv: "{{#def.c}}borde vara {{=cond}}", 307 | th: "{{#def.c}}ต้อง {{=cond}}", 308 | zh: "{{#def.c}}应当为 {{=cond}}", 309 | "zh-TW": "{{#def.c}}應該要 {{=cond}}", 310 | }, 311 | minimum: { 312 | _keywords: ["exclusiveMinimum"], 313 | _defs: { 314 | c: '{{var cond = e.params.comparison + " " + e.params.limit;}}', 315 | }, 316 | en: "{{#def.c}}must be {{=cond}}", 317 | ar: "{{#def.c}} يجب أن يكون {{=cond}}", 318 | ca: "{{#def.c}}ha de ser {{=cond}}", 319 | cs: "{{#def.c}}musí být {{=cond}}", 320 | de: "{{#def.c}}muss {{=cond}} sein", 321 | es: "{{#def.c}}debe ser {{=cond}}", 322 | fi: "{{#def.c}}täytyy olla {{=cond}}", 323 | fr: "{{#def.c}}doit être {{=cond}}", 324 | hu: "{{#def.c}}kell legyen {{=cond}}", 325 | id: "{{#def.c}}harus {{=cond}}", 326 | it: "{{#def.c}}deve essere {{=cond}}", 327 | ja: "{{#def.c}}{{=cond}}でなければいけない", 328 | ko: "{{#def.c}} {{=cond}} 이여야 합니다", 329 | nb: "{{#def.c}}må være {{=cond}}", 330 | nl: "{{#def.c}}moet {{=cond}} zijn", 331 | pl: "{{#def.c}}powinien być {{=cond}}", 332 | "pt-BR": "{{#def.c}}deve ser {{=cond}}", 333 | ru: "{{#def.c}}должно быть {{=cond}}", 334 | sk: "{{#def.c}}musí byť {{=cond}}", 335 | sv: "{{#def.c}}borde vara {{=cond}}", 336 | th: "{{#def.c}}ต้อง {{=cond}}", 337 | zh: "{{#def.c}}应当为 {{=cond}}", 338 | "zh-TW": "{{#def.c}}應該要 {{=cond}}", 339 | }, 340 | maxItems: { 341 | en: "{{#def.n}}must NOT have more than {{=n}} item{{#def.mPlural}}", 342 | ar: "{{#def.n}} يجب أن لا يحوي أكثر من {{=n}} عنصر", 343 | ca: "{{#def.n}}no ha de tenir més de {{=n}} ítem{{#def.mPlural}}", 344 | cs: "{{#def.n}}nesmí obsahovat víc než {{=n}} prv{{#def.mPlural}}", 345 | de: "{{#def.n}}darf nicht mehr als {{=n}} Element{{#def.mPlural}} haben", 346 | es: "{{#def.n}}no debe contener más de {{=n}} elemento{{#def.mPlural}}", 347 | fi: "{{#def.n}}tulee sisältää enintään {{=n}} {{? n==1 }}elementti{{??}}elementtiä{{?}}", 348 | fr: "{{#def.n}}ne doit pas contenir plus de {{=n}} élément{{#def.mPlural}}", 349 | hu: "{{#def.n}}nem lehet több, mint {{=n}} eleme", 350 | id: "{{#def.n}} tidak boleh memiliki lebih dari {{=n}} item", 351 | it: "{{#def.n}}non deve avere più di {{=n}} element{{#def.mPlural}}", 352 | ja: "{{#def.n}}は{{=n}}個以上であってはいけない", 353 | ko: "{{#def.n}}아이템이 최대 {{=n}}개이여야 합니다", 354 | nb: "{{#def.n}}kan ikke ha fler enn {{=n}} element{{#def.mPlural}}", 355 | nl: "{{#def.n}}mag niet meer dan {{=n}} item{{#def.mPlural}} bevatten", 356 | pl: "{{#def.n}}nie powinien mieć więcej niż {{=n}} element{{#def.mPlural}}", 357 | "pt-BR": "{{#def.n}}não deve ter mais que {{=n}} elemento{{#def.mPlural}}", 358 | ru: "{{#def.n}}должно иметь не более, чем {{=n}} элемент{{#def.mPlural}}", 359 | sk: "{{#def.n}}nesmie obsahovať viac než {{=n}} prv{{#def.mPlural}}", 360 | sv: "{{#def.n}}borde inte ha fler än {{=n}} sak{{#def.mPlural}}", 361 | th: "{{#def.n}}ต้องมีสมาชิกไม่เกิน {{=n}}", 362 | zh: "{{#def.n}}不应多于 {{=n}} 个项", 363 | "zh-TW": "{{#def.n}}不應該多於 {{=n}} 個", 364 | }, 365 | minItems: { 366 | en: "{{#def.n}}must NOT have less than {{=n}} item{{#def.mPlural}}", 367 | ar: "{{#def.n}} يجب أن لا يحوي أقل من {{=n}} عنصر", 368 | ca: "{{#def.n}}no ha de tenir menys de {{=n}} ítem{{#def.mPlural}}", 369 | cs: "{{#def.n}}nesmí obsahovat méně než {{=n}} prv{{#def.mPlural}}", 370 | de: "{{#def.n}}darf nicht weniger als {{=n}} Element{{#def.mPlural}} haben", 371 | es: "{{#def.n}}no debe contener menos de {{=n}} elemento{{#def.mPlural}}", 372 | fi: "{{#def.n}}tulee sisältää vähintään {{=n}} {{? n==1 }}elementti{{??}}elementtiä{{?}}", 373 | fr: "{{#def.n}}ne doit pas contenir moins de {{=n}} élément{{#def.mPlural}}", 374 | hu: "{{#def.n}}nem lehet kevesebb, mint {{=n}} eleme", 375 | id: "{{#def.n}} tidak boleh kurang dari {{=n}} item", 376 | it: "{{#def.n}}non deve avere meno di {{=n}} element{{#def.mPlural}}", 377 | ja: "{{#def.n}}は{{=n}}個以下であってはいけない", 378 | ko: "{{#def.n}}아이템이 최소 {{=n}}개이여야 합니다", 379 | nb: "{{#def.n}}kan ikke ha færre enn {{=n}} element{{#def.mPlural}}", 380 | nl: "{{#def.n}}mag niet minder dan {{=n}} item{{#def.mPlural}} bevatten", 381 | pl: "{{#def.n}}nie powinien mieć mniej niż {{=n}} element{{#def.mPlural}}", 382 | "pt-BR": "{{#def.n}}não deve ter menos que {{=n}} elemento{{#def.mPlural}}", 383 | ru: "{{#def.n}}должно иметь не менее, чем {{=n}} элемент{{#def.mPlural}}", 384 | sk: "{{#def.n}}nesmie obsahovať menej než {{=n}} prv{{#def.mPlural}}", 385 | sv: "{{#def.n}}borde inte ha färre än {{=n}} sak{{#def.mPlural}}", 386 | th: "{{#def.n}}ควรมีสมาชิกไม่น้อยกว่า {{=n}}", 387 | zh: "{{#def.n}}不应少于 {{=n}} 个项", 388 | "zh-TW": "{{#def.n}}不應該少於 {{=n}} 個", 389 | }, 390 | maxLength: { 391 | en: "{{#def.n}}must NOT be longer than {{=n}} character{{#def.mPlural}}", 392 | ar: "{{#def.n}} يجب أن لا يحوي أكثر من {{=n}} محرف", 393 | ca: "{{#def.n}}no pot contenir més de {{=n}} caràcter{{#def.mPlural}}", 394 | cs: "{{#def.n}}nesmí být delší než {{=n}} zna{{? n>=2 && n<=4 }}ky{{?? n!=1 }}k{{??}}ků{{?}}", 395 | de: "{{#def.n}}darf nicht länger als {{=n}} Zeichen sein", 396 | es: "{{#def.n}}no debe contener más de {{=n}} caracter{{? n!=1 }}es{{?}}", 397 | fi: "{{#def.n}}ei saa olla pidempi kuin {{=n}} merkki{{? n!=1 }}ä{{?}}", 398 | fr: "{{#def.n}}ne doit pas dépasser {{=n}} caractère{{#def.mPlural}}", 399 | hu: "{{#def.n}}nem lehet hosszabb, mint {{=n}} szimbólum", 400 | id: "{{#def.n}} tidak boleh lebih dari {{=n}} karakter", 401 | it: "{{#def.n}}non deve essere più lungo di {{=n}} caratter{{? n==1 }}e{{??}}i{{?}}", 402 | ja: "{{#def.n}}は{{=n}}文字以上であってはいけない", 403 | ko: "{{#def.n}}최대 {{=n}}글자여야 합니다", 404 | nb: "{{#def.n}}kan ikke være lengre enn {{=n}} tegn", 405 | nl: "{{#def.n}}mag niet langer dan {{=n}} karakter{{#def.mPlural}} zijn", 406 | pl: "{{#def.n}}nie powinien być dłuższy niż {{=n}} znak{{? n!=1 }}ów{{?}}", 407 | "pt-BR": "{{#def.n}}não deve ser maior que {{=n}} caracter{{? n!=1 }}es{{?}}", 408 | ru: "{{#def.n}}должно быть не длиннее, чем {{=n}} символ{{#def.mPlural}}", 409 | sk: "{{#def.n}}nesmie byť dlhší než {{=n}} znak{{? n!=1 }}ov{{?}}", 410 | sv: "{{#def.n}}borde inte vara längre än {{=n}} tecken", 411 | th: "{{#def.n}}ต้องยาวไม่เกิน {{=n}} ตัวอักษร", 412 | zh: "{{#def.n}}不应多于 {{=n}} 个字符", 413 | "zh-TW": "{{#def.n}}不應該多於 {{=n}} 個字元", 414 | }, 415 | minLength: { 416 | en: "{{#def.n}}must NOT be shorter than {{=n}} character{{#def.mPlural}}", 417 | ar: "{{#def.n}} يجب أن لا يحوي أقل من {{=n}} محرف", 418 | ca: "{{#def.n}}no pot contenir menys de {{=n}} caràcter{{#def.mPlural}}", 419 | cs: "{{#def.n}}nesmí být kratší než {{=n}} zna{{? n>=2 && n<=4 }}ky{{?? n!=1 }}k{{??}}ků{{?}}", 420 | de: "{{#def.n}}darf nicht kürzer als {{=n}} Zeichen sein", 421 | es: "{{#def.n}}no debe contener menos de {{=n}} caracter{{? n!=1 }}es{{?}}", 422 | fi: "{{#def.n}}ei saa olla lyhyempi kuin {{=n}} merkki{{? n!=1 }}ä{{?}}", 423 | fr: "{{#def.n}}ne doit pas faire moins de {{=n}} caractère{{#def.mPlural}}", 424 | hu: "{{#def.n}}nem lehet rövidebb, mint {{=n}} szimbólum", 425 | id: "{{#def.n}} tidak boleh lebih pendek dari {{=n}} karakter", 426 | it: "{{#def.n}}non deve essere meno lungo di {{=n}} caratter{{? n==1 }}e{{??}}i{{?}}", 427 | ja: "{{#def.n}}は{{=n}}文字以下であってはいけない", 428 | ko: "{{#def.n}}최소 {{=n}}글자여야 합니다", 429 | nb: "{{#def.n}}kan ikke være kortere enn {{=n}} tegn", 430 | nl: "{{#def.n}}mag niet korter dan {{=n}} karakter{{#def.mPlural}} zijn", 431 | pl: "{{#def.n}}nie powinien być krótszy niż {{=n}} znak{{? n!=1 }}ów{{?}}", 432 | "pt-BR": "{{#def.n}}não deve ser mais curta que {{=n}} caracter{{? n!=1 }}es{{?}}", 433 | ru: "{{#def.n}}должно быть не короче, чем {{=n}} символ{{#def.mPlural}}", 434 | sk: "{{#def.n}}nesmie byť kratší než {{=n}} znak{{? n!=1 }}ov{{?}}", 435 | sv: "{{#def.n}}borde inte vara kortare än {{=n}} tecken", 436 | th: "{{#def.n}}ต้องมีอย่างน้อย {{=n}} ตัวอักษร", 437 | zh: "{{#def.n}}不应少于 {{=n}} 个字符", 438 | "zh-TW": "{{#def.n}}不應該少於 {{=n}} 個字元", 439 | }, 440 | maxProperties: { 441 | en: "{{#def.n}}must NOT have more than {{=n}} propert{{#def.propPlural}}", 442 | ar: "{{#def.n}} يجب أن لا يحوي أكثر من {{=n}} خصائص", 443 | ca: "{{#def.n}}no pot contenir més de {{=n}} propietat{{#def.mPlural}}", 444 | cs: "{{#def.n}}nesmí mít víc než {{=n}} polož{{#def.propPlural}}", 445 | de: "{{#def.n}}darf nicht mehr als {{=n}} Attribut{{#def.propPlural}} haben", 446 | es: "{{#def.n}}no debe contener más de {{=n}} propiedad{{#def.propPlural}}", 447 | fi: "{{#def.n}}tulee sisältää enintään {{=n}} {{? n==1 }}ominaisuus{{??}}ominaisuutta{{?}}", 448 | fr: "{{#def.n}}ne doit pas contenir plus de {{=n}} propriété{{#def.propPlural}}", 449 | hu: "{{#def.n}}nem lehet több, mint {{=n}} tulajdonsága", 450 | id: "{{#def.n}} tidak boleh memiliki lebih dari {{=n}} properti", 451 | it: "{{#def.n}}non deve avere più di {{=n}} attribut{{#def.propPlural}}", 452 | ja: "{{#def.n}}は{{=n}}個以上のプロパティを有してはいけない", 453 | ko: "{{#def.n}}속성은 최대 {{=n}}개 이내여야 합니다", 454 | nb: "{{#def.n}}kan ikke ha mer enn {{=n}} egenskap{{#def.mPlural}}", 455 | nl: "{{#def.n}}mag niet meer dan {{=n}} eigenschap{{#def.propPlural}} bevatten", 456 | pl: "{{#def.n}}nie powinien zawierać więcej niż {{=n}} {{? n==1 }}pole{{??}}pól{{?}}", 457 | "pt-BR": "{{#def.n}}não deve ter mais que {{=n}} propriedade{{#def.propPlural}}", 458 | ru: "{{#def.n}}должно иметь не более, чем {{=n}} пол{{#def.propPlural}}", 459 | sk: "{{#def.n}}nesmie obsahovať viac než {{=n}} polož{{#def.propPlural}}", 460 | sv: "{{#def.n}}borde inte ha fler än {{=n}} egenskap{{#def.propPlural}}", 461 | th: "{{#def.n}}ต้องมี property ไม่เกิน {{=n}} ตัว", 462 | zh: "{{#def.n}}不应有多于 {{=n}} 个属性", 463 | "zh-TW": "{{#def.n}}不應該多於 {{=n}} 個屬性", 464 | }, 465 | minProperties: { 466 | en: "{{#def.n}}must NOT have less than {{=n}} propert{{#def.propPlural}}", 467 | ar: "{{#def.n}} يجب أن لا يحوي أقل من {{=n}} خصائص", 468 | ca: "{{#def.n}}no pot contenir menys de {{=n}} propietat{{#def.mPlural}}", 469 | cs: "{{#def.n}}nesmí mít méně než {{=n}} polož{{#def.propPlural}}", 470 | de: "{{#def.n}}darf nicht weniger als {{=n}} Attribut{{#def.propPlural}} haben", 471 | es: "{{#def.n}}no debe contener menos de {{=n}} propiedad{{#def.propPlural}}", 472 | fi: "{{#def.n}}tulee sisältää vähintään {{=n}} {{? n==1 }}ominaisuus{{??}}ominaisuutta{{?}}", 473 | fr: "{{#def.n}}ne doit pas contenir moins de {{=n}} propriété{{#def.propPlural}}", 474 | hu: "{{#def.n}}nem lehet kevesebb, mint {{=n}} tulajdonsága", 475 | id: "{{#def.n}} tidak boleh kurang dari {{=n}} properti", 476 | it: "{{#def.n}}non deve avere meno di {{=n}} attribut{{#def.propPlural}}", 477 | ja: "{{#def.n}}は{{=n}}個以下のプロパティを有してはいけない", 478 | ko: "{{#def.n}}속성은 최소 {{=n}}개 이상이여야 합니다", 479 | nb: "{{#def.n}}kan ikke ha mindre enn {{=n}} egenskap{{#def.mPlural}}", 480 | nl: "{{#def.n}}mag niet minder dan {{=n}} eigenschap{{#def.propPlural}} bevatten", 481 | pl: "{{#def.n}}nie powinien zawierać mniej niż {{=n}} {{? n==1 }}pole{{??}}pól{{?}}", 482 | "pt-BR": "{{#def.n}}não deve ter menos que {{=n}} propriedade{{#def.propPlural}}", 483 | ru: "{{#def.n}}должно иметь не менее, чем {{=n}} пол{{#def.propPlural}}", 484 | sk: "{{#def.n}}nesmie obsahovať menej než {{=n}} polož{{#def.propPlural}}", 485 | sv: "{{#def.n}}borde inte ha färre än {{=n}} egenskap{{#def.propPlural}}", 486 | th: "{{#def.n}}ต้องมี property อย่างน้อย {{=n}} ตัว", 487 | zh: "{{#def.n}}不应有少于 {{=n}} 个属性", 488 | "zh-TW": "{{#def.n}}不應該少於 {{=n}} 個屬性", 489 | }, 490 | multipleOf: { 491 | en: "must be a multiple of {{=e.params.multipleOf}}", 492 | ar: " يجب أن يحوي أكثر من {{=e.params.multipleOf}}", 493 | ca: "ha de ser múltiple de {{=e.params.multipleOf}}", 494 | cs: "musí být násobkem {{=e.params.multipleOf}}", 495 | de: "muss ein Vielfaches von {{=e.params.multipleOf}} sein", 496 | es: "debe ser múltiplo de {{=e.params.multipleOf}}", 497 | fi: "täytyy olla moninkertainen: {{=e.params.multipleOf}}", 498 | fr: "doit être un multiple de {{=e.params.multipleOf}}", 499 | hu: "a többszöröse kell legyen a következő számnak: {{=e.params.multipleOf}}", 500 | id: "harus merupakan kelipatan dari {{=e.params.multipleOf}}", 501 | it: "deve essere un multiplo di {{=e.params.multipleOf}}", 502 | ja: "{{=e.params.multipleOf}}の倍数でなければいけない", 503 | ko: "{{=e.params.multipleOf}}의 배수여야 합니다", 504 | nb: "må være et multiplum av {{=e.params.multipleOf}}", 505 | nl: "moet een veelvoud van {{=e.params.multipleOf}} zijn", 506 | pl: "powinien być wielokrotnością {{=e.params.multipleOf}}", 507 | "pt-BR": "deve ser múltiplo de {{=e.params.multipleOf}}", 508 | ru: "должно быть кратным {{=e.params.multipleOf}}", 509 | sk: "musí byť násobkom {{=e.params.multipleOf}}", 510 | sv: "borde vara en multipel av {{=e.params.multipleOf}}", 511 | th: "ต้องเป็นเลขที่หาร {{=e.params.multipleOf}} ลงตัว", 512 | zh: "应当是 {{=e.params.multipleOf}} 的整数倍", 513 | "zh-TW": "應該是 {{=e.params.multipleOf}} 的整數倍", 514 | }, 515 | not: { 516 | en: 'must NOT be valid according to schema in "not"', 517 | ar: 'يجب أن يكون غير صحيح وفقاً للمخطط "not"', 518 | ca: 'no ha de ser vàlid d’acord amb l’esquema definit a "not"', 519 | cs: 'nesmí vyhovět schématu v "not"', 520 | de: 'muss dem in "not" angegebenen Schema widersprechen', 521 | es: 'no debe ser válido según el esquema en "not"', 522 | fi: 'ei saa olla hyväksytty skeeman "not" mukaan', 523 | fr: 'est invalide selon le schéma "not"', 524 | hu: 'nem lehet érvényes a "not" alaknak megfelelően', 525 | id: 'tidak boleh valid sesuai dengan skema pada "not"', 526 | it: 'non deve essere valido in base allo schema di "non"', 527 | ja: '"not"のスキーマに従って有効としてはいけない', 528 | ko: '"not"스키마에 따라 유효하지 않아야 합니다', 529 | nb: 'kan ikke samsvare med schema i "not"', 530 | nl: 'mag niet overeenkomen met een schema in "not"', 531 | pl: 'nie powinien pasować do wzoru z sekcji "not"', 532 | "pt-BR": 'não deve ser valido segundo o schema em "not"', 533 | ru: 'должно не соответствовать схеме в "not"', 534 | sk: 'nesmie splňovať schému v "not"', 535 | sv: 'borde inte vara giltigt enligt schema i "not"', 536 | th: 'ต้องไม่ผ่าน schema ที่กำหนดไว้ใน "not"', 537 | zh: '不应当匹配 "not" schema', 538 | "zh-TW": '不應該符合 "not" schema', 539 | }, 540 | oneOf: { 541 | en: 'must match exactly one schema in "oneOf"', 542 | ar: 'يجب أن يوافق مخطط واحد فقط موجود في "oneOf"', 543 | ca: 'ha de coincidir només amb un esquema definit a "oneOf"', 544 | cs: 'musí vyhovět právě jednomu schématu v "oneOf"', 545 | de: 'muss genau einem der Schemata in "oneOf" entsprechen', 546 | es: 'debe coincidir con un solo esquema en "oneOf"', 547 | fi: 'täytyy vastata täsmälleen yhtä "oneOf" -kohdassa määriteltyä skeemaa', 548 | fr: 'doit correspondre à exactement un schéma de "oneOf"', 549 | hu: 'meg kell feleljen pontosan egy "oneOf" alaknak', 550 | id: 'harus sama persis dengan satu skema pada "oneOf"', 551 | it: 'deve corrispondere esattamente ad uno degli schema in "oneOf"', 552 | ja: '"oneOf"のスキーマと完全に一致しなくてはいけない', 553 | ko: '"oneOf" 스키마중 하나와 정확하게 일치해야 합니다', 554 | nb: 'må samsvare med nøyaktig ett schema i "oneOf"', 555 | nl: 'moet overeenkomen met één schema in "oneOf"', 556 | pl: 'powinien pasować do jednego wzoru z sekcji "oneOf"', 557 | "pt-BR": 'deve corresponder exatamente com um schema em "oneOf"', 558 | ru: 'должно соответствовать в точности одной схемe в "oneOf"', 559 | sk: 'musí splňovať práve jednu schému v "oneOf"', 560 | sv: 'borde matcha exakt ett schema i "oneOf"', 561 | th: 'ต้องตรงกับ schema ตัวเดียวใน "oneOf" เท่านั้น', 562 | zh: '只能匹配一个 "oneOf" 中的 schema', 563 | "zh-TW": '只能符合一個 "oneOf" 中的 schema', 564 | }, 565 | pattern: { 566 | en: 'must match pattern "{{=e.params.pattern}}"', 567 | ar: 'يجب أن يوافق النمط "{{=e.params.pattern}}"', 568 | ca: 'ha de coincidir amb el patró "{{=e.params.pattern}}"', 569 | cs: 'musí vyhovět regulárnímu výrazu "{{=e.params.pattern}}"', 570 | de: 'muss diesem Muster entsprechen: "{{=e.params.pattern}}"', 571 | es: 'debe coincidir con el patron "{{=e.params.pattern}}"', 572 | fi: 'täytyy vastata muotoa "{{=e.params.pattern}}"', 573 | fr: 'doit correspondre au format "{{=e.params.pattern}}"', 574 | hu: 'meg kell feleljen a következő mintának: "{{=e.params.pattern}}"', 575 | id: 'harus cocok dengan pola "{{=e.params.pattern}}"', 576 | it: 'deve corrispondere al formato "{{=e.params.pattern}}"', 577 | ja: '"{{=e.params.pattern}}"のパターンと一致しなければいけない', 578 | ko: '"{{=e.params.pattern}}"패턴과 일치해야 합니다', 579 | nb: 'må samsvare med mønsteret "{{=e.params.pattern}}"', 580 | nl: 'moet overeenkomen met het volgende patroon: "{{=e.params.pattern}}"', 581 | pl: 'powinien zgadzać się ze wzorem "{{=e.params.pattern}}"', 582 | "pt-BR": 'deve corresponder ao padrão "{{=e.params.pattern}}"', 583 | ru: 'должно соответствовать образцу "{{=e.params.pattern}}"', 584 | sk: 'musí splňovať regulárny výraz "{{=e.params.pattern}}"', 585 | sv: 'borde matcha mönstret "{{=e.params.pattern}}"', 586 | th: 'ต้องตรงตาม pattern "{{=e.params.pattern}}"', 587 | zh: '应当匹配模式 "{{=e.params.pattern}}"', 588 | "zh-TW": '應該符合模式 "{{=e.params.pattern}}"', 589 | }, 590 | required: { 591 | en: "must have required property {{=e.params.missingProperty}}", 592 | ar: "هذا الحقل إلزامي", 593 | ca: "ha de tenir la propietat requerida {{=e.params.missingProperty}}", 594 | cs: "musí obsahovat požadovanou položku {{=e.params.missingProperty}}", 595 | de: "muss das erforderliche Attribut {{=e.params.missingProperty}} enthalten", 596 | es: "debe tener la propiedad requerida {{=e.params.missingProperty}}", 597 | fi: "täytyy sisältää vaadittu ominaisuus {{=e.params.missingProperty}}", 598 | fr: "requiert la propriété {{=e.params.missingProperty}}", 599 | hu: "kell legyen {{=e.params.missingProperty}} tulajdonsága", 600 | id: "harus memiliki properti {{=e.params.missingProperty}}", 601 | it: "deve avere l'attributo obbligatorio {{=e.params.missingProperty}}", 602 | ja: "必要なプロパティ{{=e.params.missingProperty}}がなければいけない", 603 | ko: "{{=e.params.missingProperty}} 속성은 필수입니다", 604 | nb: "må ha den påkrevde egenskapen {{=e.params.missingProperty}}", 605 | nl: "moet de eigenschap {{=e.params.missingProperty}} bevatten", 606 | pl: "powinien zawierać wymagane pole {{=e.params.missingProperty}}", 607 | "pt-BR": "deve ter a propriedade obrigatória {{=e.params.missingProperty}}", 608 | ru: "должно иметь обязательное поле {{=e.params.missingProperty}}", 609 | sk: "musí obsahovať požadovanú položku {{=e.params.missingProperty}}", 610 | sv: "borde ha den nödvändiga egenskapen {{=e.params.missingProperty}}", 611 | th: "ต้องมี property {{=e.params.missingProperty}} ด้วย", 612 | zh: "应当有必需属性 {{=e.params.missingProperty}}", 613 | "zh-TW": "應該有必須屬性 {{=e.params.missingProperty}}", 614 | }, 615 | type: { 616 | _defs: { 617 | t: "{{var t = e.params.type;}}", 618 | }, 619 | en: "must be {{=e.params.type}}", 620 | ar: "قيمة هذا الحقل غير صالحة", 621 | ca: "ha de ser del tipus {{=e.params.type}}", 622 | cs: "musí být {{=e.params.type}}", 623 | de: "muss sein: {{=e.params.type}}", 624 | es: "debe ser {{=e.params.type}}", 625 | fi: '{{#def.t}}täytyy olla {{? t == "number" }}numero{{?? t == "integer"}}kokonaisluku{{?? t == "string"}}merkkijono{{?? t == "boolean"}}boolean{{??}}{{=t}}{{?}}', 626 | fr: "doit être de type {{=e.params.type}}", 627 | hu: "{{=e.params.type}} kell legyen", 628 | id: "harus berupa {{=e.params.type}}", 629 | it: "deve essere di tipo {{=e.params.type}}", 630 | ja: "{{=e.params.type}}でなければいけない", 631 | ko: "{{=e.params.type}}이여야 합니다", 632 | nb: '{{#def.t}}må være {{? t == "number" }}et tall{{?? t == "integer"}}et heltall{{?? t == "string"}}en streng{{?? t == "boolean"}}ja eller nei{{??}}{{=t}}{{?}}', 633 | nl: '{{#def.t}}moet een {{? t == "number" }}nummer{{?? t == "integer"}}geheel getal{{?? t == "string"}}tekenreeks{{?? t == "boolean"}}ja of nee waarde{{?}} ({{=t}}) bevatten', 634 | pl: "powinien być {{=e.params.type}}", 635 | "pt-BR": 636 | '{{#def.t}}deve ser {{? t == "number" }}um número{{?? t == "integer"}}um número inteiro{{?? t == "string"}}um texto{{?? t == "boolean"}}um booleano{{??}}{{=t}}{{?}}', 637 | ru: "должно быть {{=e.params.type}}", 638 | sk: "musí byť {{=e.params.type}}", 639 | sv: "borde vara {{=e.params.type}}", 640 | th: "ต้องเป็น {{=e.params.type}}", 641 | zh: "应当是 {{=e.params.type}} 类型", 642 | "zh-TW": "應該是 {{=e.params.type}} 類型", 643 | }, 644 | unevaluatedProperties: { 645 | en: "must NOT have unevaluated properties", 646 | de: "darf keine unausgewerteten Attribute haben", 647 | fi: "ei saa sisältää arvioimattomia ominaisuuksia", 648 | it: "non deve avere attributi non valutati", 649 | ko: "평가되지 않은 속성이 없어야합니다.", 650 | nl: "mag geen ongecontroleerde eigenschappen bevatten", 651 | "pt-BR": "não pode possuir propridades não avaliadas", 652 | ru: "не должно иметь непроверенных полей", 653 | th: "ต้องไม่มี property ที่ยังไม่ได้ผ่านการตรวจสอบเงื่อนไขใดๆ", 654 | zh: "不允许存在未求值的属性", 655 | "zh-TW": "不應該有未驗證的屬性", 656 | }, 657 | unevaluatedItems: { 658 | _defs: { 659 | n: "{{var n = e.params.len;}}", 660 | }, 661 | en: "{{#def.n}}must NOT have more than {{=n}} item{{#def.mPlural}}", 662 | de: "{{#def.n}}darf nicht mehr als {{=n}} Element{{#def.mPlural}} haben", 663 | fi: "{{#def.n}}ei saa olla enemmän kuin {{=n}} elementti{{? n!=1 }}ä{{?}}", 664 | it: "{{#def.n}}non deve avere più di {{=n}} elementi{{#def.mPlural}}", 665 | ko: "{{#def.n}}항목이 {{=n}}개 아이템을 초과하면 안됩니다", 666 | nl: "{{#def.n}}mag niet meer dan {{= n}} item{{#def.mPlural}} bevatten", 667 | "pt-BR": "{{#def.n}}não pode possuir mais que {{=n}} {{? n==1 }}item{{??}}itens{{?}}", 668 | ru: "{{#def.n}}должно иметь не более, чем {{=n}} элемент{{#def.mPlural}}", 669 | th: "{{#def.n}}ต้องมีไม่เกิน {{=n}} ตัว", 670 | zh: "{{#def.n}} 不允许有超过 {{=n}} 个元素", 671 | "zh-TW": "{{#def.n}} 的元素不可以超過 {{=n}} 個", 672 | }, 673 | uniqueItems: { 674 | en: "must NOT have duplicate items (items ## {{=e.params.j}} and {{=e.params.i}} are identical)", 675 | ar: "يجب أن لا يحوي عناصر مكررة (العنصر ## {{=e.params.j}} و {{=e.params.i}} متطابقة)", 676 | ca: "no ha de tenir ítems duplicats (els ítems ## {{=e.params.j}} i {{=e.params.i}} són idèntics)", 677 | cs: "nesmí obsahovat duplicitní prvky (prvky ## {{=e.params.j}} a {{=e.params.i}} jsou identické)", 678 | de: "darf keine Duplikate enthalten (Elemente #{{=e.params.j}} und #{{=e.params.i}} sind gleich)", 679 | es: "no debe contener elementos duplicados, (los elementos ## {{=e.params.j}} y {{=e.params.i}} son idénticos)", 680 | fi: "ei saa sisältää duplikaatteja (elementit ## {{=e.params.j}} ja {{=e.params.i}} ovat identtiset)", 681 | fr: "ne doit pas contenir de doublons (les éléments ## {{=e.params.j}} et {{=e.params.i}} sont identiques)", 682 | hu: "nem lehetnek azonos elemei ({{=e.params.j}} és {{=e.params.i}} elemek azonosak)", 683 | id: "tidak boleh memiliki item duplikat (item ## {{=e.params.j}} dan {{=e.params.i}} identik)", 684 | it: "non deve avere duplicati (gli elementi ## {{=e.params.j}} e {{=e.params.i}} sono uguali)", 685 | ja: "重複するアイテムがあってはいけない({{=e.params.j}}と{{=e.params.i}}は同じである)", 686 | ko: "중복 아이템이 없어야 합니다 (아이템{{=e.params.j}}과 아이템{{=e.params.i}}가 동일합니다)", 687 | nb: "kan ikke ha duplikate elemeneter (elementene ## {{=e.params.j}} og {{=e.params.i}} er identiske)", 688 | nl: "mag geen gedupliceerde items bevatten (items ## {{=e.params.j}} en {{=e.params.i}} zijn identiek)", 689 | pl: "nie powinien zawierać elementów które się powtarzają (elementy {{=e.params.j}} i {{=e.params.i}} są identyczne)", 690 | "pt-BR": 691 | "não deve ter itens duplicados (os itens ## {{=e.params.j}} e {{=e.params.i}} são idênticos)", 692 | ru: "не должно иметь повторяющихся элементов (элементы {{=e.params.j}} и {{=e.params.i}} идентичны)", 693 | sk: "nesmie obsahovať duplicitné prvky (prvky ## {{=e.params.j}} a {{=e.params.i}} sú rovnaké)", 694 | sv: "borde inte ha duplicerade saker (sakerna ## {{=e.params.j}} och {{=e.params.i}} är identiska)", 695 | th: "ต้องมีสมาชิกไม่ซ้ำักัน (ลำดับที่ {{=e.params.j}} กับ {{=e.params.i}} ซ้ำกัน)", 696 | zh: "不应当含有重复项 (第 {{=e.params.j}} 项与第 {{=e.params.i}} 项是重复的)", 697 | "zh-TW": "不應該有重複項目 (第 {{=e.params.j}} 項和第 {{=e.params.i}} 項是重複的)", 698 | }, 699 | propertyNames: { 700 | en: "property name is invalid", 701 | ar: "اسم الخاصية غير صالح", 702 | ca: "la propietat no és vàlida", 703 | cs: "název položky není platný", 704 | de: "Attributname ist ungültig", 705 | es: "la propiedad no és válida", 706 | fi: "ominaisuuden nimi on virheellinen", 707 | fr: "le nom de propriété est invalide", 708 | id: "nama properti tidak valid", 709 | it: "il nome dell'attritbuto non è valido", 710 | ko: "속성명이 올바르지 않습니다", 711 | nb: "egenskapen med navnet '{{e.params.propertyName}}' er ugyldig", 712 | nl: "eigenschapnaam is ongeldig", 713 | "pt-BR": "o nome da propriedade é inválido", 714 | ru: "имя поля не соответствует схеме", 715 | sk: "názov položky nezodpovedá schéme", 716 | sv: "egenskap med namnet är inte giltig", 717 | th: "ชื่อ property ไม่ถูกต้อง", 718 | zh: "属性名 无效", 719 | "zh-TW": "属性名 無效", 720 | }, 721 | patternRequired: { 722 | en: 'must have property matching pattern "{{=e.params.missingPattern}}"', 723 | ar: 'يجب أن يحوي خاصية توافق النمط "{{=e.params.missingPattern}}"', 724 | ca: 'la propietat ha de coincidir amb el patró "{{=e.params.missingPattern}}"', 725 | cs: 'musí obsahovat položku vyhovující regulárnímu výrazu "{{=e.params.missingPattern}}"', 726 | de: 'muss ein Attribut nach folgendem Muster haben "{{=e.params.missingPattern}}"', 727 | es: 'la propiedad debe coincidir con el patrón "{{=e.params.missingPattern}}"', 728 | fi: 'täytyy sisältää ominaisuus joka vastaa kaavaa "{{=e.params.missingPattern}}"', 729 | fr: 'la propriété doit correspondre au format "{{=e.params.missingPattern}}"', 730 | id: 'harus memiliki pola pencocokan properti "{{=e.params.missingPattern}}"', 731 | it: 'deve avere un attributo che corrisponda al formato "{{=e.params.missingPattern}}"', 732 | ko: '"{{=e.params.missingPattern}}"패턴과 일치하는 속성을 가져야 합니다', 733 | nb: 'må ha en egenskap som samsvarer med mønsteret "{{=e.params.missingPattern}}', 734 | nl: 'moet een eigenschap bevatten die overeenkomt met het pattroon: "{{=e.params.missingPattern}}"', 735 | pl: 'powinien mieć pole pasujące do wzorca "{{=e.params.missingPattern}}"', 736 | "pt-BR": 'deve ter a propriedade correspondente ao padrão "{{=e.params.missingPattern}}"', 737 | ru: 'должно иметь поле, соответствующее образцу "{{=e.params.missingPattern}}"', 738 | sk: 'musí obsahovať položku splňjúcu regulárny výraz "{{=e.params.missingPattern}}"', 739 | sv: 'bör ha en egenskap som matchar mönstret "{{=e.params.missingPattern}}"', 740 | th: 'ต้องมี property ที่มีชื่อตรงตาม pattern "{{=e.params.missingPattern}}"', 741 | zh: "应当有属性匹配模式 {{=e.params.missingPattern}}", 742 | "zh-TW": "應該有屬性對應模式 {{=e.params.missingPattern}}", 743 | }, 744 | const: { 745 | en: "must be equal to constant", 746 | ar: "يجب أن يكون ثابتاً", 747 | ca: "ha de ser igual a la constant", 748 | cs: "musí být roven konstantě", 749 | de: "muss gleich der Konstanten sein", 750 | es: "debe ser igual a la constante", 751 | fi: "täytyy olla yhtä kuin vakio", 752 | fr: "doit être égal à la constante", 753 | id: "harus sama dengan konstan", 754 | it: "deve essere uguale alla costante", 755 | ko: "상수와 같아야합니다", 756 | nb: "må være lik konstanten", 757 | nl: "moet gelijk zijn aan constante", 758 | pl: "powinien być równy stałej", 759 | "pt-BR": "deve ser igual à constante", 760 | ru: "должно быть равно заданному значению", 761 | sk: "musí byť konštanta", 762 | sv: "bör vara en konstant", 763 | th: "ต้องเท่ากับค่าคงที่", 764 | zh: "应当等于常量", 765 | "zh-TW": "應該等於常數", 766 | }, 767 | contains: { 768 | en: "must contain a valid item", 769 | ar: "يجب أن يحوي عنصرا صحيح", 770 | ca: "ha de contenir un ítem vàlid", 771 | cs: "musí obsahovat prvek odpovídající schématu", 772 | de: "muss ein valides Element enthalten", 773 | es: "debe contener un elemento válido", 774 | fi: "täytyy sisältää kelvollinen elementti", 775 | fr: "doit contenir un élément valide", 776 | id: "harus berisi item yang valid", 777 | it: "deve contentere un elemento valido", 778 | ko: "올바른 아이템을 포함해야 합니다", 779 | nb: "må inneholde et gyldig element", 780 | nl: "moet een geldig item bevatten", 781 | "pt-BR": "deve conter um item válido", 782 | ru: "должно содержать значение соответствующее схеме", 783 | sk: "musí obsahovať prvok zodpovedajúci schéme", 784 | sv: "bör innehålla ett giltigt objekt", 785 | th: "ต้องมีสมาชิกที่ผ่านเงื่อนไขอยู่", 786 | zh: "应当包含一个有效项", 787 | "zh-TW": "應該包含一個有效元素", 788 | }, 789 | formatMaximum: { 790 | _keywords: ["formatExclusiveMaximum"], 791 | _defs: { 792 | c: '{{var cond = e.params.comparison + " " + e.params.limit;}}', 793 | }, 794 | en: "{{#def.c}}must be {{=cond}}", 795 | ar: "{{#def.c}} يجب أن يكون {{=cond}}", 796 | ca: "{{#def.c}}ha de ser {{=cond}}", 797 | cs: "{{#def.c}}musí být {{=cond}}", 798 | de: "{{#def.c}}muss {{=cond}} sein", 799 | es: "{{#def.c}}debe ser {{=cond}}", 800 | fi: "{{#def.c}}täytyy olla {{=cond}}", 801 | fr: "{{#def.c}}doit être {{=cond}}", 802 | id: "{{#def.c}}harus {{=cond}}", 803 | it: "{{#def.c}}deve essere {{=cond}}", 804 | ko: "{{#def.c}} {{=cond}} 이여야 합니다", 805 | nb: "{{#def.c}}må være {{=cond}}", 806 | nl: "{{#def.c}}moet {{=cond}} zijn", 807 | pl: "{{#def.c}}powinien być {{=cond}}", 808 | "pt-BR": "{{#def.c}}deve ser {{=cond}}", 809 | ru: "{{#def.c}}должно быть {{=cond}}", 810 | sk: "{{#def.c}}musí byť {{=cond}}", 811 | sv: "{{#def.c}}bör vara {{=cond}}", 812 | th: "{{#def.c}}ต้อง {{=cond}}", 813 | zh: "{{#def.c}}应当是 {{=cond}}", 814 | "zh-TW": "{{#def.c}}應該是 {{=cond}}", 815 | }, 816 | formatMinimum: { 817 | _keywords: ["formatExclusiveMinimum"], 818 | _defs: { 819 | c: '{{var cond = e.params.comparison + " " + e.params.limit;}}', 820 | }, 821 | en: "{{#def.c}}must be {{=cond}}", 822 | ar: "{{#def.c}} يجب أن يكون {{=cond}}", 823 | ca: "{{#def.c}}ha de ser {{=cond}}", 824 | cs: "{{#def.c}}musí být {{=cond}}", 825 | de: "{{#def.c}}muss {{=cond}} sein", 826 | es: "{{#def.c}}debe ser {{=cond}}", 827 | fi: "{{#def.c}}täytyy olla {{=cond}}", 828 | fr: "{{#def.c}}doit être {{=cond}}", 829 | id: "{{#def.c}}harus {{=cond}}", 830 | it: "{{#def.c}}deve essere {{=cond}}", 831 | ko: "{{#def.c}} {{=cond}} 이여야 합니다", 832 | nb: "{{#def.c}}må være {{=cond}}", 833 | nl: "{{#def.c}}moet {{=cond}} zijn", 834 | pl: "{{#def.c}}powinien być {{=cond}}", 835 | "pt-BR": "{{#def.c}}deve ser {{=cond}}", 836 | ru: "{{#def.c}}должно быть {{=cond}}", 837 | sk: "{{#def.c}}musí byť {{=cond}}", 838 | sv: "{{#def.c}}bör vara {{=cond}}", 839 | th: "{{#def.c}}ต้อง {{=cond}}", 840 | zh: "{{#def.c}}应当是 {{=cond}}", 841 | "zh-TW": "{{#def.c}}應該是 {{=cond}}", 842 | }, 843 | if: { 844 | en: 'must match "{{=e.params.failingKeyword}}" schema', 845 | ar: 'يجب أن توافق المخطط "{{=e.params.failingKeyword}}"', 846 | ca: 'ha de correspondre’s amb l’esquema "{{=e.params.failingKeyword}}"', 847 | cs: 'musí vyhovět "{{=e.params.failingKeyword}}" schématu', 848 | de: 'muss dem Schema "{{=e.params.failingKeyword}}" entsprechen', 849 | es: 'debe corresponderse con el esquema "{{=e.params.failingKeyword}}"', 850 | fi: 'täytyy vastata "{{=e.params.failingKeyword}}" skeemaa', 851 | fr: 'doit correspondre au schéma "{{=e.params.failingKeyword}}"', 852 | id: 'harus cocok dengan skema "{{=e.params.failingKeyword}}"', 853 | it: 'deve corrispondere allo schema "{{=e.params.failingKeyword}}"', 854 | ko: '"{{=e.params.failingKeyword}}" 스키마와 일치해야 합니다', 855 | nl: 'moet overeenkomen met "{{=e.params.failingKeyword}}" schema', 856 | "pt-BR": 'deve corresponder ao schema "{{=e.params.failingKeyword}}"', 857 | ru: 'должно соответствовать схемe "{{=e.params.failingKeyword}}"', 858 | th: 'ต้องตรงกับ schema "{{=e.params.failingKeyword}}"', 859 | zh: '应当匹配模式 "{{=e.params.failingKeyword}}" ', 860 | "zh-TW": '應該符合 "{{=e.params.failingKeyword}}" schema', 861 | }, 862 | discriminator: { 863 | _type: false, 864 | tag: { 865 | en: 'tag "{{=e.params.tag}}" must be string', 866 | de: 'der Tag "{{=e.params.tag}}" muss eine Zeichenkette sein', 867 | fi: 'tunniste "{{=e.params.tag}}" täytyy olla merkkijono', 868 | it: 'il tag "{{=e.params.tag}}" deve essere di tipo stringa', 869 | ko: '"{{=e.params.tag}}"태그는 반드시 문자열이여야 합니다', 870 | nl: 'tag "{{=e.params.tag}}" moet een tekenreeks zijn', 871 | "pt-BR": 'a tag "{{=e.params.tag}}" deve ser uma string', 872 | ru: 'поле "{{=e.params.tag}}" должно быть строкой', 873 | th: 'tag "{{=e.params.tag}}" ต้องเป็น string', 874 | zh: '标签 "{{=e.params.tag}}" 的类型必须为字符串', 875 | "zh-TW": '標籤 "{{=e.params.tag}}" 的類型必須是字串', 876 | }, 877 | mapping: { 878 | en: 'value of tag "{{=e.params.tag}}" must be in oneOf', 879 | de: 'der Wert vom Tag "{{=e.params.tag}}" muss im oneOf enthalten sein', 880 | fi: 'tunnisteen "{{=e.params.tag}}" arvon muoto pitää olla oneOf', 881 | it: 'il valore del tag "{{=e.params.tag}}" deve essere nei oneOf', 882 | ko: '"{{=e.params.tag}}"태그의 값은 반드시 oneOf에 있어야 합니다', 883 | nl: 'de waarde van het veld "{{= e.params.tag}}" moet voorkomen in de oneOf', 884 | "pt-BR": 'o valor da tag "{{=e.params.tag}}" deve estar no oneOf', 885 | ru: 'значение поля "{{=e.params.tag}}" должно быть в одной из oneOf схем ', 886 | th: 'ต้องมีค่าของ tag "{{=e.params.tag}}" ใน oneOf', 887 | zh: '标签 "{{=e.params.tag}}" 的值必须在 oneOf 之中', 888 | "zh-TW": '標籤 "{{=e.params.tag}}" 必須在 oneOf 其中之一', 889 | }, 890 | }, 891 | } 892 | -------------------------------------------------------------------------------- /messages/jtd.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | /** 4 | * When adding new locales, please maintain alphabetic ordering. 5 | * "en" should remain in the first position. 6 | * Tests will fail otherwise. 7 | */ 8 | 9 | module.exports = { 10 | // supported locales 11 | _locales: [ 12 | "en", 13 | "ca", 14 | "cs", 15 | "de", 16 | "es", 17 | "fi", 18 | "fr", 19 | "hu", 20 | "id", 21 | "it", 22 | "ja", 23 | "ko", 24 | "nb", 25 | "nl", 26 | "pl", 27 | "pt-BR", 28 | "ru", 29 | "sk", 30 | "sv", 31 | "th", 32 | "zh", 33 | "zh-TW", 34 | ], 35 | 36 | // shared defines 37 | _defs: {}, 38 | 39 | // error messages 40 | _defaultMessage: { 41 | en: 'must pass "{{=e.keyword}}" keyword validation', 42 | ca: 'ha de passar la validació de la clau "{{=e.keyword}}"', 43 | cs: 'musí vyhovět "{{=e.keyword}}" validaci', 44 | de: 'muss die Validierung "{{=e.keyword}}" bestehen', 45 | es: 'debe pasar la validación de palabra clave "{{=e.keyword}}"', 46 | fi: 'täytyy läpäistä "{{=e.keyword}}" avainsanatarkistus', 47 | fr: 'doit être valide selon le critère "{{=e.keyword}}"', 48 | id: 'harus lulus validasi kata kunci "{{=e.keyword}}"', 49 | it: 'deve essere valido secondo il criterio "{{=e.keyword}}"', 50 | ko: '"{{=e.keyword}}"키워드 검사를 통과해야 합니다', 51 | nb: "må samsvare med valideringen for {{=e.keyword}}", 52 | nl: 'moet sleutelwoord validatie "{{=e.keyword}}" doorstaan', 53 | pl: 'powinien przejść walidację "{{=e.keyword}}"', 54 | "pt-BR": 'deve passar a validação da keyword "{{=e.keyword}}"', 55 | ru: 'должно соответствовать правилу "{{=e.keyword}}"', 56 | sk: 'musí splniť "{{=e.keyword}}" validáciu', 57 | sv: 'bör passera "{{=e.keyword}}" nyckelord validering', 58 | th: 'ต้องผ่านคีย์เวิร์ด "{{=e.keyword}}"', 59 | zh: '应当通过 "{{=e.keyword}} 关键词校验"', 60 | "zh-TW": '應該通過 "{{=e.keyword}} 關鍵詞檢驗"', 61 | }, 62 | 63 | _type: { 64 | _defs: { 65 | t: "{{var t = e.params.type; var n = e.params.nullable ? '/null' : '';}}", 66 | }, 67 | en: "{{#def.t}}must be {{=t+n}}", 68 | ca: "{{#def.t}}ha de ser del tipus {{=t+n}}", 69 | cs: "{{#def.t}}musí být {{=t+n}}", 70 | de: "{{#def.t}}muss sein: {{=t+n}}", 71 | es: "{{#def.t}}debe ser {{=t+n}}", 72 | fi: "{{#def.t}}täytyy olla {{=t+n}}", 73 | fr: "{{#def.t}}doit être de type {{=t+n}}", 74 | hu: "{{#def.t}}{{=t+n}} kell legyen", 75 | id: "{{#def.t}}harus berupa {{=t+n}}", 76 | it: "{{#def.t}}deve essere di tipo {{=t+n}}", 77 | ja: "{{#def.t}}{{=t+n}}でなければいけない", 78 | ko: "{{#def.t}}{{=t+n}}이여야 합니다", 79 | nb: '{{#def.t}}må være {{? t == "number" }}et tall{{?? t == "integer"}}et heltall{{?? t == "string"}}en streng{{?? t == "boolean"}}ja eller nei{{??}}{{=t}}{{?}}{{=n}}', 80 | nl: '{{#def.t}}moet een {{? t == "number" }}nummer{{?? t == "integer"}}geheel getal{{?? t == "string"}}tekenreeks{{?? t == "boolean"}}ja of nee waarde{{?}}{{=n}} ({{=t}}) bevatten', 81 | pl: "{{#def.t}}powinien być {{=t+n}}", 82 | "pt-BR": 83 | '{{#def.t}}deve ser {{? t == "number" }}um número{{?? t == "integer"}}um número inteiro{{?? t == "string"}}um texto{{?? t == "boolean"}}um booleano{{??}}{{=t}}{{?}}{{=n}}', 84 | ru: "{{#def.t}}должно быть {{=t+n}}", 85 | sk: "{{#def.t}}musí byť {{=t+n}}", 86 | sv: "{{#def.t}}borde vara {{=t+n}}", 87 | th: "{{#def.t}}ต้องเป็น {{=t+n}}", 88 | zh: "{{#def.t}}应当是 {{=t+n}} 类型", 89 | "zh-TW": "{{#def.t}}應該是 {{=t+n}} 類型", 90 | }, 91 | 92 | type: { 93 | _keywords: ["elements", "values"], 94 | _type: true, 95 | }, 96 | 97 | properties: { 98 | _type: true, 99 | additional: { 100 | en: "must NOT have additional properties", 101 | ca: "no ha de tenir propietats addicionals", 102 | cs: "nemůže mít další položky", 103 | de: "darf keine zusätzlichen Attribute haben", 104 | es: "no debe tener propiedades adicionales", 105 | fi: "ei saa sisältää ylimääräisiä ominaisuuksia", 106 | fr: "ne doit pas contenir de propriétés additionnelles", 107 | hu: "nem lehetnek további elemei", 108 | id: "tidak boleh memiliki properti tambahan", 109 | it: "non deve avere attributi addizionali", 110 | ja: "追加してはいけない", 111 | ko: "추가적인 속성은 허용되지 않습니다", 112 | nb: "kan ikke ha flere egenskaper", 113 | nl: "mag geen extra eigenschappen bevatten", 114 | pl: "nie powinien zawierać dodatkowych pól", 115 | "pt-BR": "não deve ter propriedades adicionais", 116 | ru: "не должно иметь дополнительных полей", 117 | sk: "nemôže obsahovať ďalšie položky", 118 | sv: "borde inte ha fler egenskaper", 119 | th: "ต้องไม่มี property อื่นๆ นอกเหนีอจากที่กำหนดไว้", 120 | zh: "不允许有额外的属性", 121 | "zh-TW": "不可以有額外的屬性", 122 | }, 123 | missing: { 124 | en: "must have property {{=e.params.missingProperty}}", 125 | ca: "ha de tenir la propietat requerida {{=e.params.missingProperty}}", 126 | cs: "musí obsahovat požadovanou položku {{=e.params.missingProperty}}", 127 | de: "muss das erforderliche Attribut {{=e.params.missingProperty}} enthalten", 128 | es: "debe tener la propiedad requerida {{=e.params.missingProperty}}", 129 | fi: "täytyy sisältää ominaisuus {{=e.params.missingProperty}}", 130 | fr: "requiert la propriété {{=e.params.missingProperty}}", 131 | hu: "kell legyen {{=e.params.missingProperty}} tulajdonsága", 132 | id: "harus memiliki properti {{=e.params.missingProperty}}", 133 | it: "deve avere l'attributo obbligatorio {{=e.params.missingProperty}}", 134 | ja: "必要なプロパティ{{=e.params.missingProperty}}がなければいけない", 135 | ko: "{{=e.params.missingProperty}} 속성은 필수입니다", 136 | nb: "må ha den påkrevde egenskapen {{=e.params.missingProperty}}", 137 | nl: "moet de eigenschap {{=e.params.missingProperty}} bevatten", 138 | pl: "powinien zawierać wymagane pole {{=e.params.missingProperty}}", 139 | "pt-BR": "deve ter a propriedade obrigatória {{=e.params.missingProperty}}", 140 | ru: "должно иметь обязательное поле {{=e.params.missingProperty}}", 141 | sk: "musí obsahovať požadovanú položku {{=e.params.missingProperty}}", 142 | sv: "borde ha den nödvändiga egenskapen {{=e.params.missingProperty}}", 143 | th: "ต้องมี property {{=e.params.missingProperty}} ด้วย", 144 | zh: "应当有必需属性 {{=e.params.missingProperty}}", 145 | "zh-TW": "應該有必須屬性 {{=e.params.missingProperty}}", 146 | }, 147 | }, 148 | 149 | discriminator: { 150 | _type: true, 151 | tag: { 152 | en: 'tag "{{=e.params.tag}}" must be string', 153 | de: 'der Tag "{{=e.params.tag}}" muss eine Zeichenkette sein', 154 | fi: 'tunniste "{{=e.params.tag}}" täytyy olla merkkijono', 155 | it: 'il tag "{{=e.params.tag}}" deve essere di tipo stringa', 156 | ko: '"{{=e.params.tag}}"태그는 문자열이여야 합니다', 157 | nl: 'tag "{{=e.params.tag}}" moet een tekenreeks zijn', 158 | "pt-BR": 'a tag "{{=e.params.tag}}" deve ser uma string', 159 | ru: 'поле "{{=e.params.tag}}" должно быть строкой', 160 | th: 'tag "{{=e.params.tag}}" ต้องเป็น string', 161 | zh: '标签 "{{=e.params.tag}}" 的类型必须为字符串', 162 | "zh-TW": '標籤 "{{=e.params.tag}}" 的類型必須是字串', 163 | }, 164 | mapping: { 165 | en: 'value of tag "{{=e.params.tag}}" must be in mapping', 166 | de: 'der Wert vom Tag "{{=e.params.tag}}" muss im Mapping enthalten sein', 167 | fi: 'tunnisteen arvon "{{=e.params.tag}}" on oltava kartoituksessa', 168 | it: 'il valore del tag "{{=e.params.tag}}" deve essere nei mapping', 169 | ko: '"{{=e.params.tag}}"태그의 값은 반드시 매핑에 있어야합니다.', 170 | nl: 'de waarde van het veld "{{= e.params.tag}}" moet voorkomen in de mapping', 171 | "pt-BR": 'o valor da tag "{{=e.params.tag}}" deve estar no mapping', 172 | ru: 'значение поля "{{=e.params.tag}}" должно быть ключом одной из схем', 173 | th: 'ต้องมีค่าของ tag "{{=e.params.tag}}" ใน mapping', 174 | zh: '标签 "{{=e.params.tag}}" 的值必须在 mapping 之中', 175 | "zh-TW": '標籤 "{{=e.params.tag}}" 必須在 mapping 其中之一', 176 | }, 177 | }, 178 | 179 | enum: { 180 | en: "must be equal to one of the allowed values", 181 | ca: "ha de ser igual a un dels valors predefinits", 182 | cs: "musí být rovno jedné hodnotě z výčtu", 183 | de: "muss einem der vorgegebenen Werte entsprechen", 184 | es: "deber ser igual a uno de los valores predefinidos", 185 | fi: "täytyy olla yhtä kuin jokin sallituista arvoista", 186 | fr: "doit être égal à une des valeurs prédéfinies", 187 | hu: "egyenlő kell legyen valamely előre meghatározott értékkel", 188 | id: "harus sama dengan salah satu dari nilai yang telah ditentukan", 189 | it: "dovrebbe essere uguale ad uno dei valori predefiniti", 190 | ja: "事前に定義された値のいずれかに等しくなければいけない", 191 | ko: "미리 정의된 값중 하나여야 합니다", 192 | nb: "må være lik en av de forhåndsdefinerte verdiene", 193 | nl: "moet overeenkomen met één van de voorgedefinieerde waarden", 194 | pl: "powinien być równy jednej z predefiniowanych wartości", 195 | "pt-BR": "deve ser igual a um dos valores permitidos", 196 | ru: "должно быть равно одному из разрешенных значений", 197 | sk: "musí byť jedna z definovaných hodnôt", 198 | sv: "borde vara ekvivalent med en av dess fördefinierade värden", 199 | th: "ต้องตรงกับหนึ่งในค่าที่กำหนดไว้", 200 | zh: "应当是预设定的枚举值之一", 201 | "zh-TW": "應該要在預設的值之中", 202 | }, 203 | 204 | union: { 205 | en: 'must match a schema in "union"', 206 | ca: 'ha de coincidir amb algun esquema definit a "union"', 207 | cs: 'musí vyhovět alespoň jednomu schématu v "union"', 208 | de: 'muss einem der Schemata in "union" entsprechen', 209 | es: 'debe coincidir con algún esquema en "union"', 210 | fi: 'täytyy vastata "union" skeemaa', 211 | fr: 'doit correspondre à un schéma de "union"', 212 | hu: 'meg kell feleljen legalább egy "union" alaknak', 213 | id: 'harus cocok dengan beberapa skema pada "union"', 214 | it: 'deve corrispondere ad uno schema in "union"', 215 | ja: '"union"のスキーマとマッチしなくてはいけない', 216 | ko: '"union"의 스키마와 일치해야 합니다', 217 | nb: 'må samsvare med et schema i "union"', 218 | nl: 'moet overeenkomen met een schema in "union"', 219 | pl: 'powinien pasować do wzoru z sekcji "union"', 220 | "pt-BR": 'os dados não correspondem a nenhum schema de "union"', 221 | ru: 'должно соответствовать одной их схем в "union"', 222 | sk: 'musí splňovať aspoň jednu zo schém v "union"', 223 | sv: 'borde matcha något schema i "union"', 224 | th: 'ต้องตรงกับหนึ่งใน schema ที่กำหนดไว้ใน "union"', 225 | zh: "数据应为 union 所指定的其中一个", 226 | "zh-TW": "不符合 union 指定的模式", 227 | }, 228 | } 229 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ajv-i18n", 3 | "version": "4.2.0", 4 | "description": "Internationalised error messages for Ajv JSON validator", 5 | "main": "localize/index.js", 6 | "types": "localize/index.d.ts", 7 | "files": [ 8 | "localize/", 9 | "LICENSE" 10 | ], 11 | "scripts": { 12 | "build": "npm run build:json-schema && npm run build:jtd", 13 | "build:json-schema": "node scripts/compile-locales.js '' index", 14 | "build:jtd": "node scripts/compile-locales.js '/jtd' jtd", 15 | "eslint": "eslint messages scripts spec/*.js", 16 | "prepublish": "npm run build", 17 | "test": "npm run prettier:check && npm run eslint && npm run build && npm run test-cov", 18 | "test-spec": "mocha spec/*.spec.js -R dot", 19 | "test-cov": "nyc npm run test-spec", 20 | "prettier:write": "prettier --write \"./**/*.{json,yaml,js,ts}\"", 21 | "prettier:check": "prettier --list-different \"./**/*.{json,yaml,js,ts}\"" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/epoberezkin/ajv-i18n.git" 26 | }, 27 | "keywords": [ 28 | "ajv", 29 | "JSON", 30 | "schema", 31 | "i18n", 32 | "internationalisation" 33 | ], 34 | "author": "Evgeny Poberezkin", 35 | "license": "MIT", 36 | "bugs": { 37 | "url": "https://github.com/epoberezkin/ajv-i18n/issues" 38 | }, 39 | "homepage": "https://github.com/epoberezkin/ajv-i18n#readme", 40 | "devDependencies": { 41 | "@ajv-validator/config": "^0.3.0", 42 | "ajv": "^8.0.0", 43 | "ajv-formats": "^2.0.0", 44 | "ajv-keywords": "^5.0.0", 45 | "dot": "^1.0.3", 46 | "eslint": "^7.8.1", 47 | "eslint-config-prettier": "^8.1.0", 48 | "husky": "^7.0.1", 49 | "json-schema-test": "^2.0.0", 50 | "lint-staged": "^11.1.1", 51 | "mocha": "^9.0.3", 52 | "nyc": "^15.0.0", 53 | "prettier": "^2.2.1" 54 | }, 55 | "peerDependencies": { 56 | "ajv": "^8.0.0-beta.0" 57 | }, 58 | "nyc": { 59 | "exclude": [ 60 | "**/spec/**", 61 | "node_modules" 62 | ], 63 | "reporter": [ 64 | "lcov", 65 | "text-summary" 66 | ] 67 | }, 68 | "prettier": "@ajv-validator/config/prettierrc.json", 69 | "husky": { 70 | "hooks": { 71 | "pre-commit": "lint-staged && npm test" 72 | } 73 | }, 74 | "lint-staged": { 75 | "*.{json,yaml,js,ts}": "prettier --write" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /scripts/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | rules: 2 | no-console: 0 3 | no-empty: [2, allowEmptyCatch: true] 4 | dot-notation: [2, allowPattern: "^en$"] 5 | -------------------------------------------------------------------------------- /scripts/compile-locales.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const doT = require("dot") 4 | const prettier = require("prettier") 5 | const fs = require("fs") 6 | const path = require("path") 7 | let totalMissing = 0 8 | 9 | const [, , importFile, localeFileName] = process.argv 10 | const localeFile = `${localeFileName}.js` 11 | const localeDefFile = `${localeFileName}.d.ts` 12 | 13 | const errorMessages = require(path.join("../messages", importFile)) 14 | 15 | const localize = getTemplate("localize.jst") 16 | const localizeDef = getTemplate("localize.d.jst") 17 | 18 | errorMessages._locales.forEach(compileMessages) 19 | saveLocales() 20 | console.log("Total missing messages:", totalMissing) 21 | 22 | function compileMessages(locale) { 23 | const localeDirPath = path.join(__dirname, "..", "localize", locale) 24 | const localePath = path.join(localeDirPath, localeFile) 25 | const localeDefPath = path.join(localeDirPath, localeDefFile) 26 | 27 | try { 28 | fs.mkdirSync(localeDirPath) 29 | } catch (e) {} 30 | const code = localize(localeMessages(locale)) 31 | const defCode = localizeDef() 32 | saveCode(localePath, code) 33 | saveCode(localeDefPath, defCode) 34 | } 35 | 36 | function saveLocales() { 37 | const indexDirPath = path.join(__dirname, "..", "localize") 38 | const indexPath = path.join(indexDirPath, localeFile) 39 | const indexDefPath = path.join(indexDirPath, localeDefFile) 40 | const renderIndex = getTemplate("index.jst") 41 | const renderDefIndex = getTemplate("index.d.jst") 42 | 43 | const code = renderIndex({locales: errorMessages._locales, importFile}) 44 | const defCode = renderDefIndex({locales: errorMessages._locales, importFile}) 45 | saveCode(indexPath, code) 46 | saveCode(indexDefPath, defCode) 47 | } 48 | 49 | function saveCode(filepath, code) { 50 | code = prettier.format(code, {semi: false, filepath}) 51 | fs.writeFileSync(filepath, code) 52 | } 53 | 54 | function localeMessages(locale) { 55 | const messages = [] 56 | const localeDefs = getLocaleDefs(errorMessages._defs, locale) 57 | const enDefs = getLocaleDefs(errorMessages._defs, "en") 58 | 59 | for (const keyword in errorMessages) { 60 | if (keyword[0] === "_") continue 61 | const msgFunc = compileMessage(keyword) 62 | if (msgFunc) messages.push({keyword, msgFunc, keywords: errorMessages[keyword]._keywords}) 63 | } 64 | messages.sort(byKeyword) 65 | return { 66 | locale, 67 | messages, 68 | defaultMessage: compileMessage("_defaultMessage"), 69 | typeMessage: compileMessage("_type"), 70 | } 71 | 72 | function compileMessage(keyword) { 73 | const keyMsgs = errorMessages[keyword] 74 | if (!keyMsgs) return undefined 75 | if (keyMsgs._type !== undefined) { 76 | const msgFuncs = [] 77 | for (const error in keyMsgs) { 78 | if (error[0] === "_") continue 79 | const func = compileMsgFunc(keyMsgs[error], `${keyword}/${error}`) 80 | msgFuncs.push({error, func}) 81 | } 82 | return msgFuncs 83 | } else { 84 | return compileMsgFunc(keyMsgs, keyword) 85 | } 86 | } 87 | 88 | function compileMsgFunc(_keyMsgs, keyword) { 89 | const keyDefs = _keyMsgs._defs 90 | let msg = _keyMsgs[locale] 91 | let defs 92 | 93 | if (msg) { 94 | defs = localeDefs 95 | } else { 96 | defs = enDefs 97 | totalMissing++ 98 | msg = _keyMsgs["en"] 99 | const errorMsg = `message for locale "${locale}" keyword "${keyword}"` 100 | if (msg) { 101 | console.warn(`Warning: Replaced with "en" ${errorMsg}`) 102 | } else { 103 | throw new Error(`Error: No ${errorMsg}`) 104 | } 105 | } 106 | 107 | if (keyDefs) defs = {...defs, ...keyDefs} 108 | 109 | return doT.compile(msg, defs) 110 | } 111 | } 112 | 113 | function getLocaleDefs(defs, locale) { 114 | const localeDefs = {} 115 | for (const key in defs) { 116 | const def = defs[key] 117 | localeDefs[key] = typeof def == "string" ? def : def[locale] 118 | } 119 | return localeDefs 120 | } 121 | 122 | function byKeyword(a, b) { 123 | return a.keyword.localeCompare(b.keyword) 124 | } 125 | 126 | function getTemplate(fileName) { 127 | const tmplStr = fs.readFileSync(path.join(__dirname, "..", "localize", fileName)) 128 | return doT.compile(tmplStr) 129 | } 130 | -------------------------------------------------------------------------------- /scripts/prepare-tests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | mkdir -p .browser 6 | 7 | ls spec | grep .spec.js | \ 8 | xargs -I {} sh -c \ 9 | 'export f="{}"; browserify spec/$f -t require-globify -t brfs -x ajv -o .browser/$f;' 10 | 11 | -------------------------------------------------------------------------------- /spec/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | globals: 2 | describe: false 3 | it: false 4 | before: false 5 | -------------------------------------------------------------------------------- /spec/localize-jtd.spec.js: -------------------------------------------------------------------------------- 1 | const AjvJTD = require("ajv/dist/jtd").default 2 | const jtdValidationTests = require("./json-typedef-spec/tests/validation.json") 3 | const assert = require("assert") 4 | const localize = require("../localize/jtd") 5 | 6 | const ONLY = [] 7 | 8 | describe("JSON Type Definition errors with ajv-i18n", function () { 9 | let ajvs 10 | this.timeout(30000) 11 | 12 | before(() => { 13 | ajvs = [getAjv(false, false), getAjv(false, true), getAjv(true, false), getAjv(true, true)] 14 | }) 15 | 16 | for (const testName in jtdValidationTests) { 17 | const {schema, instance, errors} = jtdValidationTests[testName] 18 | const valid = errors.length === 0 19 | describeOnly(testName, () => { 20 | if (valid) { 21 | it("should be valid", () => 22 | ajvs.forEach((ajv) => assert.strictEqual(ajv.validate(schema, instance), valid))) 23 | } else { 24 | it("should be invalid", () => { 25 | ajvs.forEach((ajv) => { 26 | assert.strictEqual(ajv.validate(schema, instance), valid) 27 | for (const locale in localize) { 28 | localize[locale](ajv.errors) 29 | ajv.errors.forEach((err) => assertStr(err.message)) 30 | const text = ajv.errorsText(undefined, {separator: "\n"}) 31 | // if (locale == "en") console.log(text) 32 | assertStr(text) 33 | ajv.errors.forEach((err) => { 34 | delete err.message 35 | }) 36 | } 37 | }) 38 | }) 39 | } 40 | }) 41 | } 42 | }) 43 | 44 | function getAjv(allErrors, verbose) { 45 | return new AjvJTD({allErrors, verbose, messages: false}) 46 | } 47 | 48 | function assertStr(str) { 49 | assert.strictEqual(typeof str, "string") 50 | assert(str.length > 0) 51 | assert.strictEqual(str.indexOf("undefined"), -1) 52 | } 53 | 54 | function describeOnly(name, func) { 55 | if (ONLY.length === 0 || ONLY.some((p) => p.test(name))) { 56 | describe(name, func) 57 | } else { 58 | describe.skip(name, func) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /spec/localize.spec.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const localize = require("../localize") 4 | 5 | const jsonSchemaTest = require("json-schema-test") 6 | const Ajv = require("ajv").default 7 | const Ajv2019 = require("ajv/dist/2019").default 8 | const ajvKeywords = require("ajv-keywords") 9 | const ajvFormats = require("ajv-formats") 10 | const assert = require("assert") 11 | const {toHash} = require("ajv/dist/compile/util") 12 | 13 | const remoteRefs = { 14 | "http://localhost:1234/integer.json": require("./JSON-Schema-Test-Suite/remotes/integer.json"), 15 | "http://localhost:1234/subSchemas.json": require("./JSON-Schema-Test-Suite/remotes/subSchemas.json"), 16 | "http://localhost:1234/subSchemas-defs.json": require("./JSON-Schema-Test-Suite/remotes/subSchemas-defs.json"), 17 | "http://localhost:1234/baseUriChange/folderInteger.json": require("./JSON-Schema-Test-Suite/remotes/baseUriChange/folderInteger.json"), 18 | "http://localhost:1234/baseUriChangeFolder/folderInteger.json": require("./JSON-Schema-Test-Suite/remotes/baseUriChangeFolder/folderInteger.json"), 19 | "http://localhost:1234/baseUriChangeFolderInSubschema/folderInteger.json": require("./JSON-Schema-Test-Suite/remotes/baseUriChangeFolderInSubschema/folderInteger.json"), 20 | "http://localhost:1234/name.json": require("./JSON-Schema-Test-Suite/remotes/name.json"), 21 | "http://localhost:1234/name-defs.json": require("./JSON-Schema-Test-Suite/remotes/name-defs.json"), 22 | } 23 | 24 | const SKIP_DRAFT7 = [ 25 | "format/idn-email", 26 | "format/idn-hostname", 27 | "format/iri", 28 | "format/iri-reference", 29 | "optional/content", 30 | "optional/float-overflow", 31 | ] 32 | 33 | const SKIP = { 34 | draft6: ["optional/float-overflow"], 35 | draft7: SKIP_DRAFT7, 36 | "draft2019-09": [...SKIP_DRAFT7, "recursiveRef"], 37 | } 38 | 39 | const DEFAULT_META = { 40 | draft6: "http://json-schema.org/draft-06/schema#", 41 | } 42 | 43 | const suites = { 44 | draft6: "./JSON-Schema-Test-Suite/tests/draft6/{**/,}*.json", 45 | draft7: "./JSON-Schema-Test-Suite/tests/draft7/{**/,}*.json", 46 | "draft2019-09": "./JSON-Schema-Test-Suite/tests/draft2019-09/{**/,}*.json", 47 | "ajv-keywords": "./ajv-keywords/spec/tests/patternRequired.json", 48 | "ajv-formats": "./ajv-formats/tests/extras/format{Minimum,Maximum}.json", 49 | } 50 | 51 | for (const s in suites) runTests(s) 52 | 53 | function runTests(suite) { 54 | const instances = [ 55 | getAjv(suite, false, false), 56 | getAjv(suite, false, true), 57 | getAjv(suite, true, false), 58 | getAjv(suite, true, true), 59 | ] 60 | 61 | instances.forEach((ajv) => { 62 | addRemoteRefs(ajv) 63 | if (DEFAULT_META[suite]) { 64 | ajv.opts.defaultMeta = DEFAULT_META[suite] 65 | } 66 | }) 67 | 68 | const tests = {} 69 | tests[suite] = suites[suite] 70 | 71 | jsonSchemaTest(instances, { 72 | description: "Schema tests of " + instances.length + " ajv instances with ajv-i18n", 73 | suites: tests, 74 | afterEach: afterEach, 75 | skip: SKIP[suite], 76 | assert: assert, 77 | cwd: __dirname, 78 | hideFolder: `${suite}/`, 79 | timeout: 30000, 80 | }) 81 | } 82 | 83 | function getAjv(suite, allErrors, verbose) { 84 | let ajv 85 | const options = { 86 | strict: false, 87 | logger: false, 88 | messages: false, 89 | allErrors, 90 | verbose, 91 | formats: toHash(["idn-email", "idn-hostname", "iri", "iri-reference"]), 92 | } 93 | switch (suite) { 94 | case "draft2019-09": 95 | ajv = new Ajv2019(options) 96 | break 97 | default: 98 | ajv = new Ajv({...options, ignoreKeywordsWithRef: true}) 99 | ajv.addMetaSchema(require("ajv/lib/refs/json-schema-draft-06.json")) 100 | } 101 | ajvFormats(ajvKeywords(ajv, ["patternRequired"]), {keywords: true}) 102 | return ajv 103 | } 104 | 105 | function afterEach(res) { 106 | if (res.valid) return 107 | for (const locale in localize) { 108 | localize[locale](res.errors) 109 | res.errors.forEach((err) => { 110 | assertStr(err.message) 111 | }) 112 | const text = res.validator.errorsText(undefined, {separator: "\n"}) 113 | // if (locale == 'en') console.log(text); 114 | assertStr(text) 115 | res.errors.forEach((err) => { 116 | delete err.message 117 | }) 118 | } 119 | } 120 | 121 | function assertStr(str) { 122 | assert.strictEqual(typeof str, "string") 123 | assert(str.length > 0) 124 | // TODO enable this check - fails on unevaluatedItems 125 | // assert.strictEqual(str.indexOf("undefined"), -1) 126 | } 127 | 128 | function addRemoteRefs(ajv) { 129 | for (const id in remoteRefs) { 130 | ajv.addSchema(remoteRefs[id], id) 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /spec/style.spec.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const messages = require("../messages") 4 | const jtdMessages = require("../messages/jtd") 5 | const localize = require("../localize") 6 | const jtdLocalize = require("../localize/jtd") 7 | const assert = require("assert") 8 | 9 | describe("code style: ordering of locales", () => { 10 | describe("JSON Schema", () => { 11 | it("locales in index.js should be ordered (en first)", () => testLocalesProperties(localize)) 12 | 13 | it("_locales should be ordered (en first)", () => testLocalesOrder(messages._locales)) 14 | 15 | it("locales in _defs should be ordered (en first)", () => { 16 | testLocalesProperties(messages._defs.mPlural, "_defs.mPlural") 17 | testLocalesProperties(messages._defs.propPlural, "_defs.propPlural") 18 | }) 19 | 20 | it("locales in keywords should be ordered (en first)", () => { 21 | for (const keyword in messages) { 22 | if (keyword[0] === "_") continue 23 | testLocalesProperties(messages[keyword], "keyword " + keyword) 24 | } 25 | }) 26 | }) 27 | 28 | describe("JSON Type Definition", () => { 29 | it("locales in index.js should be ordered (en first)", () => testLocalesProperties(jtdLocalize)) 30 | 31 | it("_locales should be ordered (en first)", () => testLocalesOrder(jtdMessages._locales)) 32 | 33 | it("locales in keywords should be ordered (en first)", () => { 34 | for (const keyword in jtdMessages) { 35 | if (keyword[0] === "_") continue 36 | testLocalesProperties(jtdMessages[keyword], "keyword " + keyword) 37 | } 38 | }) 39 | }) 40 | }) 41 | 42 | function testLocalesOrder(locales, message) { 43 | assert.strictEqual(locales[0], "en", message) 44 | const ordered = ["en"].concat(locales.slice(1).sort()) 45 | assert.deepStrictEqual(locales, ordered, message) 46 | } 47 | 48 | function testLocalesProperties(obj, message) { 49 | if (obj && obj._type !== undefined) { 50 | for (const errorType in obj) { 51 | if (errorType[0] === "_") continue 52 | testLocalesProperties(obj[errorType], `${message} (${errorType})`) 53 | } 54 | } else { 55 | const props = Object.keys(obj) 56 | while (props[0][0] === "_") props.shift() 57 | testLocalesOrder(props, message) 58 | } 59 | } 60 | --------------------------------------------------------------------------------