Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
thebergamo committed Feb 11, 2016
1 parent 432492e commit e8513f7
Show file tree
Hide file tree
Showing 7 changed files with 395 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "4"
- "5"
env:
- EXPORT_COVERAGE=1
85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Joi18nz

[![Build Status][travis-badge]][travis-url]
[![Coverage Status][coveralls-badge]][coveralls-url]
[![Dependency Status][david-badge]][david-url]

Internacionlization(i18n) error messages for [Joi](https://github.com/hapijs/joi)

### Getting Started
For using Joi18nz is very simple:
```javascript
'use strict';
const Joi = require('joi18nz')(require('joi'), __dirname + '/locale');
```
You must send to joi18nz an intance of Joi and the directory of the translation files.

After, initializing the module, you have the instance of Joi, and you can use that like you use Joi.

You can translate your messages, simple adding an extra option in your validate function.

```javascript
let schema = {
name: Joi.string().required()
};

let value = {};

Joi.validate(value, schema, {i18n: 'pt_BR'}, function (err, data) {
console.log(err, data);
});
// output
/*
{ [ValidationError: falha em "name", pois ["name" é obrigatório]]
isJoi: true,
name: 'ValidationError',
details:
[ { message: '"name" é obrigatório',
path: 'name',
type: 'any.required',
context: [Object] } ],
_object: {},
annotate: [Function] } {}
*/
```

For more information about how translate the tokens, you can see the `pt_BR` translation inside the `i18n` directory in this project.

**NOTE:** If you specify an invalid path to your folders we just use the default english version for the errors or the translations default in the `i18n` directory in this project.

After all, you just have a Joi instance, you can use that like you use Joi in your project, no incompatibilities with an existing implementation.

### Contribute

To contribute you can try to find an [issue or enchancment][0] and try to
implement it. Fork the project, implement the code, make tests and send the PR to the master branch.

### Testing

For testing you just need run `npm install && npm test` inside root folder of this project.

### License

Copyright (c) 2016, Marcos Bérgamo <marcos@thedon.com.br>

Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.

[0]: https://github.com/thebergamo/joi18nz/issues?q=is%3Aopen+is%3Aenchancement+is%3Abug

[travis-badge]: https://api.travis-ci.org/thebergamo/joi18nz.svg?branch=master
[travis-url]: https://travis-ci.org/thebergamo/joi18nz
[coveralls-badge]:https://coveralls.io/repos/thebergamo/joi18nz/badge.svg?branch=master&service=github
[coveralls-url]: https://coveralls.io/github/thebergamo/joi18nz?branch=master
[david-badge]: https://david-dm.org/thebergamo/joi18nz.svg
[david-url]: https://david-dm.org/thebergamo/joi18nz

118 changes: 118 additions & 0 deletions i18n/pt_BR.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

{
"root": "value",
"key": "\"{{!key}}\" ",
"messages": {
"wrapArrays": true
},
"any": {
"unknown": "não é permitido",
"invalid": "contém um valor inválido",
"empty": "não é permitido ser vazio",
"required": "é obrigatório",
"allowOnly": "precisa ser um dos seguintes valores: {{valids}}",
"default": "ocorreu um erro ao executar o método padrão"
},
"alternatives": {
"base": "não corresponde a nenhuma altenativa válida"
},
"array": {
"base": "deve ser uma matriz",
"includes": "na posição {{pos}} não corresponde a nenhuma tipo válido",
"includesSingle": "valor único de \"{{!key}}\" não corresponde a nenhuma tipo válido",
"includesOne": "na posição {{pos}} falha, pois {{reason}}",
"includesOneSingle": "valor único de \"{{!key}}\" falha, pois {{reason}}",
"includesRequiredUnknowns": "não contém {{unknownMisses}} valor(es) obrigatório(s)",
"includesRequiredKnowns": "não contém {{knownMisses}}",
"includesRequiredBoth": "não contém {{knownMisses}} e {{unknownMisses}} outros valor(es) obrigatório(s)",
"excludes": "na posição {{pos}} contém um valor excluído",
"excludesSingle": "valor único de \"{{!key}}\" contém um valor excluído",
"min": "deve conter no mínimo {{limit}} itens",
"max": "deve conter menos que ou igual a {{limit}} itens",
"length": "deve conter {{limit}} itens",
"ordered": "na posição {{pos}} falha, pois {{reason}}",
"orderedLength": "na posição {{pos}} falha, pois a matriz deve conter até {{limit}} itens",
"sparse": "não pode ser uma matriz esparsa",
"unique": "na posição {{pos}} há um valor duplicado"
},
"boolean": {
"base": "deve ser boleano"
},
"binary": {
"base": "deve ser um buffer ou uma string",
"min": "deve conter no mínimo {{limit}} bytes",
"max": "deve conter no máximo {{limit}} bytes",
"length": "deve conter {{limit}} bytes"
},
"date": {
"base": "deve ser um número em milisegundos ou uma data válida",
"min": "deve ser maior ou igual a \"{{limit}}\"",
"max": "deve ser menor ou igual a \"{{limit}}\"",
"isoDate": "deve ser uma data no padrão ISO 8601",
"ref": "referencia a \"{{ref}}\" que não é uma data"
},
"function": {
"base": "deve ser uma função"
},
"object": {
"base": "deve ser um objeto",
"child": "falha em \"{{!key}}\", pois {{reason}}",
"min": "deve conter no mínimo {{limit}} filhos",
"max": "deve conter no máximo {{limit}} filhos",
"length": "deve conter {{limit}} filhos",
"allowUnknown": "não é permitido",
"with": "peer obrigatório não encontrado: \"{{peer}}\"",
"without": "peer conflitante ou proibido: \"{{peer}}\"",
"missing": "deve conter ao menos {{peers}}",
"xor": "contém um conflito entre peers exclusivos {{peers}}",
"or": "deve conter algum dos peers {{peers}}",
"and": "contém {{present}} sem seus peers obrigatórios {{missing}}",
"nand": "!!\"{{main}}\" não deve existir juntamente com {{peers}}",
"assert": "!!\"{{ref}}\" validação falha, pois \"{{ref}}\" falhou em {{message}}",
"rename": {
"multiple": "não pôde renomear \"{{from}}\" pois muitas renomeaçãoes estão desativadas e já havia sido renomeado para \"{{to}}\"",
"override": "não pôde renomear \"{{from}}\" pois sobrescrever está desabilitado e \"{{to}}\" já existe"
},
"type": "deve ser um instância de \"{{type}}\""
},
"number": {
"base": "deve ser um número",
"min": "deve ser maior ou igual a {{limit}}",
"max": "deve ser menor ou igual a {{limit}}",
"less": "deve ser menor que {{limit}}",
"greater": "deve ser maior que {{limit}}",
"float": "deve ser um número decimal",
"integer": "deve ser um número inteiro",
"negative": "deve ser um número negativo",
"positive": "deve ser um número positivo",
"precision": "não pode conter mais que {{limit}} casas decimais",
"ref": "referencia a \"{{ref}}\" na qual não é um número",
"multiple": "deve ser múltiplo de {{multiple}}"
},
"string": {
"base": "deve ser um texto",
"min": "deve conter no mínimo {{limit}} caracteres",
"max": "deve conter no máximo {{limit}} caracteres",
"length": "deve conter {{limit}} caracteres",
"alphanum": "deve conter apenas caracteres alpha-numéricos",
"token": "deve conter apenas caracteres alpha-numéricos ou underscore '_'",
"regex": {
"base": "com o valor \"{{!value}}\" falha ao comparar ao padrão: {{pattern}}",
"name": "com o valor \"{{!value}}\" falha ao comparar ao padrão: {{name}}"
},
"email": "deve ser um email válido",
"uri": "dever ser uma URI válida",
"uriCustomScheme": "dever ser uma URI válida que se assemelhe ao padrão {{scheme}}",
"isoDate": "deve ser uma data no padrão ISO 8601",
"guid": "deve ser um GUID válido",
"hex": "deve conter apenas valores hexadecimais",
"hostname": "deve conter apenas hostname válido",
"lowercase": "deve conter apenas caracteres em caixa baixa",
"uppercase": "deve conter apenas caracteres em caixa alta",
"trim": "não deve haver espaços em branco",
"creditCard": "deve ser um cartão de crédito",
"ref": "referencia a \"{{ref}}\" que não é um número",
"ip": "deve ser um IP válido com o CIDR {{cidr}}",
"ipVersion": "deve ser um IP válido nas versões {{version}} com o CIDR {{cidr}}"
}
}
52 changes: 52 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use strict';

const fs = require('fs');
const Path = require('path');

const internals = {};

internals.i18n = function (Joi, i18nDir) {
const directory = i18nDir || '';
if (!Joi) {
throw new TypeError('Joi is required');
}

const originalFn = Joi.validate;
Joi.validate = function (value /*, [schema], [options], callback */) {
const last = arguments[arguments.length - 1];
const callback = typeof last === 'function' ? last : null;

const count = arguments.length - (callback ? 1 : 0);
if (count === 1) {
return originalFn(value, callback);
}

const options = count === 3 ? arguments[2] : {};

if (options.i18n) {
options.language = internals.getI18nFile(directory, options.i18n);
delete options.i18n;
}

const schema = arguments[1];

return originalFn(value, schema, options, callback);
};

return Joi;
};

internals.getI18nFile = function (i18nDir, fileName) {
try {
const root = Path.join(i18nDir, fileName + '.json');
const isFile = fs.statSync(root).isFile();
return isFile ? require(root) : {};
} catch (err) {
console.error(err);

return {};
}
};

module.exports = internals.i18n;

25 changes: 25 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "joi18nz",
"version": "1.0.0",
"description": "Internacionlization(i18n) error messages for Joi",
"repository": "https://github.com/thebergamo/joi18nz",
"main": "index.js",
"scripts": {
"test": "scripts/test"
},
"keywords": [
"joi",
"i18n",
"translation"
],
"author": "Marcos Bérgamo <marcos@thedon.com.br>",
"license": "ISC",
"dependencies": {},
"devDependencies": {
"code": "~2.1.0",
"coveralls": "~2.11.6",
"joi": "~7.2.3",
"lab": "~8.2.0",
"semistandard": "~7.0.5"
}
}
29 changes: 29 additions & 0 deletions scripts/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/sh

# script/test: Run test suite for application. Optionally pass in a path to an
# individual test file to run a single test.


set -e

cd "$(dirname "$0")/.."

[ -z "$DEBUG" ] || set -x

echo "===> Running linter..."

./node_modules/semistandard/bin/cmd.js

echo "===> Running tests..."

if [ ! -z "$EXPORT_COVERAGE" ]; then
mkdir -p coverage

./node_modules/.bin/lab -c -l -t 95 -v -r lcov > ./coverage/lab.lcov

cat ./coverage/lab.lcov | ./node_modules/coveralls/bin/coveralls.js

rm -rf ./coverage
else
./node_modules/.bin/lab -c -l -t 95 -v
fi
Loading

0 comments on commit e8513f7

Please sign in to comment.