Ir al contenido

Códigos de error y mensajes traducidos

Cuando un valor no es válido, validate() explica por qué con cuatro campos de error:

  • code: qué clase de error es, uno de siete códigos, para que tu código pueda actuar según el caso;
  • rule: el identificador de la regla de SPEC.md que no se cumple, como DNI-2;
  • message: una frase para el usuario, en el idioma que indiques;
  • expected: solo si el carácter de control es incorrecto, el correcto, para sugerir «¿quisiste decir…?».
import { validate } from "nif-dni-nie-cif-validation";
validate("12345678A").error;
// { code: "INVALID_CONTROL_CHARACTER", rule: "DNI-2", expected: "Z",
// message: 'The control character is not correct: for this DNI it should be "Z".' }

validate() comprueba el valor paso a paso y se detiene en el primer fallo, así que un valor no válido tiene exactamente un error. type y normalized están presentes en cuanto el formato es reconocible, aunque el carácter de control sea incorrecto.

error.code Cuándo
NOT_A_STRING El valor no es una cadena de texto (null, un número, un objeto). Nunca se convierte en una
EMPTY El valor está vacío, o solo tiene espacios y separadores
INVALID_LENGTH El valor no tiene el número de caracteres de su tipo
INVALID_FORMAT Un carácter que el formato no admite: un primer carácter incorrecto, una letra donde va un dígito (o un dígito donde va la letra de control) o un prefijo ES sin allowVatPrefix
INVALID_CONTROL_CHARACTER El formato es correcto, pero la letra o el dígito de control no; expected contiene el correcto
UNSUPPORTED_TYPE Un documento válido de un tipo que types excluye
PLACEHOLDER Un número de ejemplo (00000000T, 00000001R, 99999999R, X0000000T) con rejectPlaceholders: true

Los dos últimos solo se producen con una opción: con las opciones por defecto, un documento válido siempre es válido.

La tabla siguiente recoge, para cada código, todas las reglas de SPEC que puede citar y el mensaje que lo acompaña, en el idioma de esta página. Los mensajes salen de la propia librería, así que son exactamente los que verán tus usuarios.

Todos los códigos de error de validate(), cada regla de SPEC que pueden citar, una entrada que los produce y su mensaje en español
ReglaEjemploMensaje
Código: NOT_A_STRING
INPUT-1nullEl valor debe ser un texto.
Código: EMPTY
INPUT-2" - "Introduce un NIF, NIE o CIF.
Código: INVALID_LENGTH
DNI-1"1234567890"Un DNI tiene 9 caracteres: 8 dígitos y una letra.
KLM-1"K123456"Un NIF K/L/M tiene 9 caracteres: K, L o M, 7 dígitos y una letra.
NIE-1"X123456"Un NIE tiene 9 caracteres: X, Y o Z, 7 dígitos y una letra.
NIE-3"X11234567L"Solo los NIE antiguos tienen 10 caracteres: X, un 0, 7 dígitos y una letra.
CIF-1"B123456"Un NIF de persona jurídica o entidad (CIF) tiene 9 caracteres: una letra, 7 dígitos y un carácter de control.
VAT-1"ES", { allowVatPrefix: true }Un NIF-IVA español es ES seguido de un NIF de 9 caracteres.
Código: INVALID_FORMAT
NIF-1"T1234567A"No es un NIF, NIE ni CIF: debe empezar por un dígito o por una letra válida.
VAT-1"ES12345678Z"Introduce el NIF sin el prefijo ES.
DNI-1"123456789"Un DNI son 8 dígitos seguidos de una letra.
KLM-1"K12345678"Un NIF K/L/M empieza por K, L o M, seguido de 7 dígitos y una letra.
KLM-3"K12345A7L"Los 7 caracteres que siguen a K, L o M deben ser dígitos.
NIE-1"X12345678"Un NIE empieza por X, Y o Z, seguido de 7 dígitos y una letra.
CIF-1"B12A45674"Un NIF de persona jurídica o entidad (CIF) consta de una letra, 7 dígitos y un carácter de control (un dígito o una letra).
Código: INVALID_CONTROL_CHARACTER
DNI-2"12345678A"El carácter de control no es correcto: para este DNI debería ser «Z».
DNI-3"12345678I"El carácter de control no es correcto: para este DNI debería ser «Z».
KLM-2"K1234567A"El carácter de control no es correcto: para este NIF K/L/M debería ser «L».
NIE-2"Y1234567L"El carácter de control no es correcto: para este NIE debería ser «X».
CIF-3"G1234567D"El carácter de control no es correcto: para este NIF de persona jurídica o entidad (CIF) debería ser «4».
CIF-4"B12345675"El carácter de control no es correcto: para este NIF de persona jurídica o entidad (CIF) debería ser «4».
Código: UNSUPPORTED_TYPE
POLICY-2"B12345674", { types: ["DNI", "NIE"] }Aquí no se admite un NIF de persona jurídica o entidad (CIF).
Código: PLACEHOLDER
POLICY-1"00000000T", { rejectPlaceholders: true }Este número figura en la lista de valores de ejemplo que no se admiten aquí.

La regla distingue casos que comparten código. Por ejemplo, INVALID_CONTROL_CHARACTER cita DNI-3 cuando la letra es una que nunca aparece (I, Ñ, O, U), CIF-3 cuando el control de un CIF es una letra y la clave lleva un dígito (o al revés) y CIF-4 cuando es de la clase correcta pero tiene un valor incorrecto:

import { validate } from "nif-dni-nie-cif-validation";
validate("12345678I").error?.rule; // "DNI-3"
validate("B1234567A").error?.rule; // "CIF-3": la B lleva dígito
validate("B12345675").error?.rule; // "CIF-4": un dígito, pero el que no es
validate("T1234567A").error?.rule; // "NIF-1": ningún NIF empieza por T
validate("X11234567L").error?.rule; // "NIE-3": 10 caracteres, pero no es la forma antigua del NIE

El inglés viene incluido. Cada uno de los demás idiomas es un punto de entrada aparte, así que un bundle solo contiene los idiomas que importa. Importa el objeto del idioma y pásalo como locale:

Idioma Importación
Inglés (por defecto) import { en } from "nif-dni-nie-cif-validation/locales/en"
Español import { es } from "nif-dni-nie-cif-validation/locales/es"
Catalán (català), también para el valenciano import { ca } from "nif-dni-nie-cif-validation/locales/ca"
Euskera import { eu } from "nif-dni-nie-cif-validation/locales/eu"
Gallego (galego) import { gl } from "nif-dni-nie-cif-validation/locales/gl"
import { describeCifOrganisation, validate } from "nif-dni-nie-cif-validation";
import { eu } from "nif-dni-nie-cif-validation/locales/eu";
validate("12345678A", { locale: eu }).error?.message;
// "Kontrol-karakterea ez da zuzena: NAN honetan «Z» izan beharko luke."
describeCifOrganisation("B", eu); // "Erantzukizun mugatuko sozietatea"

El mismo objeto de idioma sirve en todas partes: como opción locale de validate() y de todos los esquemas (zNif({ locale }), vNif({ locale }), yNif({ locale })), y como segundo argumento de describeCifOrganisation(). También traduce meta.orgDescription, el tipo de entidad de un CIF.

Para seguir el idioma del usuario, asigna un objeto de idioma a cada etiqueta de idioma, con uno por defecto:

import { type NifLocale, validate } from "nif-dni-nie-cif-validation";
import { ca } from "nif-dni-nie-cif-validation/locales/ca";
import { en } from "nif-dni-nie-cif-validation/locales/en";
import { es } from "nif-dni-nie-cif-validation/locales/es";
const LOCALES: Record<string, NifLocale> = { ca, en, es };
const localeFor = (language: string) => LOCALES[language.slice(0, 2)] ?? en;
const locale = localeFor("ca-ES"); // por ejemplo, navigator.language
validate("12345678A", { locale }).error?.message;
// "El caràcter de control no és correcte: per a aquest DNI hauria de ser «Z»."
validate("B12345674", { locale }).meta?.orgDescription; // "Societat de responsabilitat limitada"

El catalán sirve también para el valenciano: la AEAT da los mismos nombres de entidad en ambos, y los mensajes no usan ninguna forma que difiera entre los dos.

code y rule son estables, así que puedes asociarlos a tus propios textos y usar el mensaje de la librería como alternativa:

import { type NifErrorCode, validate } from "nif-dni-nie-cif-validation";
const MESSAGES: Partial<Record<NifErrorCode, string>> = {
EMPTY: "Please enter your tax ID.",
UNSUPPORTED_TYPE: "Please enter a personal tax ID, not a company's.",
};
const error = validate("B12345674", { types: ["DNI", "NIE"] }).error;
error && (MESSAGES[error.code] ?? error.message); // "Please enter a personal tax ID, not a company's."

Un idioma es un objeto normal (NifLocale), así que también puedes escribir uno para otro idioma. Si a un objeto de idioma le falta un texto, se usa el inglés para ese texto. La terminología y las fuentes de cada nombre de entidad traducido están en docs/translations.md (en inglés).

Los esquemas de Zod, Valibot y Yup dan el mismo mensaje, y ponen el código y la regla donde cada librería lo permite:

Librería Mensaje Código y regla
Zod el message del issue los params del issue: { code, rule, expected? }
Valibot el message del issue el propio issue: issue.code, issue.rule, issue.expected
Yup el message del ValidationError los params del error: { code, rule, expected? }

Consulta Validar formularios para ver ejemplos.