or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-validation.mdcountry-validation.mdcrypto-validation.mdencoding-validation.mdfinancial-validation.mdi18n-validation.mdindex.mdnetwork-validation.mdsystem-validation.md

i18n-validation.mddocs/

0

# Internationalization Validation

1

2

Validators for country-specific personal and business identifiers. These validators implement local validation rules, check digits, and format requirements for national identification systems.

3

4

## Capabilities

5

6

### Spanish Identifiers

7

8

Validators for Spanish national identification documents and tax codes.

9

10

```python { .api }

11

def es_cif(value: str, /) -> Union[Literal[True], ValidationError]:

12

"""

13

Validate Spanish CIF (Código de Identificación Fiscal) - company tax ID.

14

15

Parameters:

16

- value: CIF string to validate

17

18

Returns:

19

True if valid CIF, ValidationError otherwise

20

21

Format: 8 characters + 1 check digit

22

- First character: Letter indicating organization type (A-N, P, Q, R, S, W)

23

- Next 7 characters: Numbers

24

- Last character: Check digit (letter or number)

25

26

Used for companies, associations, and other entities in Spain.

27

"""

28

29

def es_nif(value: str, /) -> Union[Literal[True], ValidationError]:

30

"""

31

Validate Spanish NIF (Número de Identificación Fiscal) - personal tax ID.

32

33

Parameters:

34

- value: NIF string to validate

35

36

Returns:

37

True if valid NIF, ValidationError otherwise

38

39

Format: 8 digits + 1 check letter

40

- 8 digits: Personal identification number

41

- 1 letter: Check letter calculated from the digits

42

43

Used for Spanish nationals and residents.

44

"""

45

46

def es_nie(value: str, /) -> Union[Literal[True], ValidationError]:

47

"""

48

Validate Spanish NIE (Número de Identidad de Extranjero) - foreigner ID.

49

50

Parameters:

51

- value: NIE string to validate

52

53

Returns:

54

True if valid NIE, ValidationError otherwise

55

56

Format: 1 letter + 7 digits + 1 check letter

57

- First letter: X, Y, or Z

58

- 7 digits: Sequential number

59

- Check letter: Calculated from the number

60

61

Used for foreigners with legal residence in Spain.

62

"""

63

64

def es_doi(value: str, /) -> Union[Literal[True], ValidationError]:

65

"""

66

Validate Spanish DOI (Documento de Identidad) - any Spanish digital identity.

67

68

Parameters:

69

- value: DOI string to validate

70

71

Returns:

72

True if valid DOI, ValidationError otherwise

73

74

Validates any of: NIF, NIE, or CIF

75

Used as a general validator for Spanish identification documents.

76

"""

77

```

78

79

### Finnish Identifiers

80

81

Validators for Finnish national identification and business codes.

82

83

```python { .api }

84

def fi_business_id(value: str, /) -> Union[Literal[True], ValidationError]:

85

"""

86

Validate Finnish business ID (Y-tunnus).

87

88

Parameters:

89

- value: Finnish business ID string to validate

90

91

Returns:

92

True if valid business ID, ValidationError otherwise

93

94

Format: 7 digits + hyphen + 1 check digit

95

- Example: 1234567-8

96

- Check digit calculated using modulo 11 algorithm

97

98

Used for all Finnish companies and organizations.

99

"""

100

101

def fi_ssn(value: str, /, *, allow_temporal_ssn: bool = True) -> Union[Literal[True], ValidationError]:

102

"""

103

Validate Finnish Social Security Number (Henkilötunnus).

104

105

Parameters:

106

- value: Finnish SSN string to validate

107

- allow_temporal_ssn: Allow temporal SSNs (900-999 birth numbers)

108

109

Returns:

110

True if valid SSN, ValidationError otherwise

111

112

Format: DDMMYY-NNNC or DDMMYY+NNNC or DDMMYYANNC

113

- DDMMYY: Birth date

114

- Separator: - (1900s), + (1800s), A (2000s)

115

- NNN: Individual number (002-899 normal, 900-999 temporal)

116

- C: Check character

117

118

Used for all Finnish residents.

119

"""

120

```

121

122

### French Identifiers

123

124

Validators for French national codes and administrative identifiers.

125

126

```python { .api }

127

def fr_department(value: Union[str, int], /) -> Union[Literal[True], ValidationError]:

128

"""

129

Validate French department numbers.

130

131

Parameters:

132

- value: Department number (string or integer)

133

134

Returns:

135

True if valid department number, ValidationError otherwise

136

137

Validates French administrative department codes:

138

- Metropolitan France: 01-95 (excluding 20)

139

- Corsica: 2A, 2B (or 201, 202)

140

- Overseas departments: 971, 972, 973, 974, 976

141

- Overseas collectivities: 975, 977, 978, 984-988

142

"""

143

144

def fr_ssn(value: str, /) -> Union[Literal[True], ValidationError]:

145

"""

146

Validate French Social Security Number (Numéro de Sécurité Sociale).

147

148

Parameters:

149

- value: French SSN string to validate

150

151

Returns:

152

True if valid SSN, ValidationError otherwise

153

154

Format: 15 digits (often displayed with spaces as groups)

155

- 1 digit: Gender (1=male, 2=female, 7-8=temporary)

156

- 2 digits: Birth year (last 2 digits)

157

- 2 digits: Birth month (01-12)

158

- 2 digits: Birth department

159

- 3 digits: Birth commune

160

- 3 digits: Birth order number

161

- 2 digits: Check digits (97 - (first 13 digits mod 97))

162

163

Also known as INSEE number.

164

"""

165

```

166

167

### Indian Identifiers

168

169

Validators for Indian national identification documents.

170

171

```python { .api }

172

def ind_aadhar(value: str, /) -> Union[Literal[True], ValidationError]:

173

"""

174

Validate Indian Aadhar card numbers.

175

176

Parameters:

177

- value: Aadhar number string to validate

178

179

Returns:

180

True if valid Aadhar number, ValidationError otherwise

181

182

Format: 12 digits

183

- No leading zeros in first digit

184

- Uses Verhoeff check digit algorithm

185

- Example: 1234 5678 9012

186

187

Unique identification number for Indian residents.

188

"""

189

190

def ind_pan(value: str, /) -> Union[Literal[True], ValidationError]:

191

"""

192

Validate Indian PAN (Permanent Account Number) card numbers.

193

194

Parameters:

195

- value: PAN string to validate

196

197

Returns:

198

True if valid PAN, ValidationError otherwise

199

200

Format: 10 characters (AAAAA9999A)

201

- First 5: Letters

202

- Next 4: Digits

203

- Last 1: Letter (check character)

204

- Example: ABCDE1234F

205

206

Used for tax identification in India.

207

"""

208

```

209

210

### Russian Identifiers

211

212

Validators for Russian tax and business identifiers.

213

214

```python { .api }

215

def ru_inn(value: str, /) -> Union[Literal[True], ValidationError]:

216

"""

217

Validate Russian INN (Individual Taxpayer Number).

218

219

Parameters:

220

- value: INN string to validate

221

222

Returns:

223

True if valid INN, ValidationError otherwise

224

225

Formats:

226

- 10 digits: Legal entities (companies)

227

- 12 digits: Individual taxpayers

228

229

Uses specific check digit algorithms for validation.

230

Required for all Russian taxpayers.

231

"""

232

```

233

234

## Usage Examples

235

236

```python

237

import validators

238

239

# Spanish identifiers

240

validators.es_nif('12345678Z') # True (personal tax ID)

241

validators.es_nie('X1234567L') # True (foreigner ID)

242

validators.es_cif('A12345674') # True (company tax ID)

243

validators.es_doi('12345678Z') # True (validates any Spanish ID)

244

245

# Finnish identifiers

246

validators.fi_business_id('1234567-8') # True

247

validators.fi_ssn('311280-999J') # True

248

validators.fi_ssn('311280-999J', allow_temporal_ssn=False) # May be False if temporal

249

250

# French identifiers

251

validators.fr_department('75') # True (Paris)

252

validators.fr_department(75) # True (accepts int)

253

validators.fr_department('2A') # True (Corsica)

254

validators.fr_ssn('123456789012345') # True (if valid checksum)

255

256

# Indian identifiers

257

validators.ind_aadhar('123456789012') # True (if valid Verhoeff check)

258

validators.ind_pan('ABCDE1234F') # True

259

260

# Russian identifiers

261

validators.ru_inn('1234567890') # True (10-digit legal entity)

262

validators.ru_inn('123456789012') # True (12-digit individual)

263

```

264

265

## Advanced Usage

266

267

### Multi-Country ID Validation

268

269

```python

270

import validators

271

272

def validate_national_id(country: str, id_value: str) -> dict:

273

"""Validate national ID based on country."""

274

275

country_validators = {

276

'ES': {

277

'nif': validators.es_nif,

278

'nie': validators.es_nie,

279

'cif': validators.es_cif,

280

'any': validators.es_doi

281

},

282

'FI': {

283

'ssn': validators.fi_ssn,

284

'business': validators.fi_business_id

285

},

286

'FR': {

287

'ssn': validators.fr_ssn,

288

},

289

'IN': {

290

'aadhar': validators.ind_aadhar,

291

'pan': validators.ind_pan

292

},

293

'RU': {

294

'inn': validators.ru_inn

295

}

296

}

297

298

if country not in country_validators:

299

return {'supported': False, 'results': {}}

300

301

results = {}

302

for id_type, validator in country_validators[country].items():

303

results[id_type] = bool(validator(id_value))

304

305

return {

306

'supported': True,

307

'results': results,

308

'any_valid': any(results.values())

309

}

310

311

# Usage

312

result = validate_national_id('ES', '12345678Z')

313

print(f"Spanish ID validation: {result}")

314

```

315

316

### ID Format Detection

317

318

```python

319

import validators

320

321

def detect_id_format(id_value: str) -> list:

322

"""Detect possible ID formats for a given value."""

323

324

possible_formats = []

325

326

# Test against all available validators

327

validators_to_test = [

328

('Spanish NIF', validators.es_nif),

329

('Spanish NIE', validators.es_nie),

330

('Spanish CIF', validators.es_cif),

331

('Finnish SSN', validators.fi_ssn),

332

('Finnish Business', validators.fi_business_id),

333

('French SSN', validators.fr_ssn),

334

('Indian Aadhar', validators.ind_aadhar),

335

('Indian PAN', validators.ind_pan),

336

('Russian INN', validators.ru_inn),

337

]

338

339

for format_name, validator in validators_to_test:

340

if validator(id_value):

341

possible_formats.append(format_name)

342

343

return possible_formats

344

345

# Usage

346

test_ids = [

347

'12345678Z', # Spanish NIF format

348

'X1234567L', # Spanish NIE format

349

'1234567-8', # Finnish business ID format

350

'ABCDE1234F', # Indian PAN format

351

]

352

353

for test_id in test_ids:

354

formats = detect_id_format(test_id)

355

print(f"{test_id}: {formats}")

356

```

357

358

## Validation Rules Summary

359

360

### Check Digit Algorithms Used

361

362

- **Spanish NIF/NIE**: Modulo 23 with letter mapping

363

- **Spanish CIF**: Complex algorithm based on organization type

364

- **Finnish Business ID**: Modulo 11 algorithm

365

- **Finnish SSN**: Modulo 31 with character mapping

366

- **French SSN**: Modulo 97 algorithm

367

- **Indian Aadhar**: Verhoeff algorithm

368

- **Indian PAN**: Format validation only

369

- **Russian INN**: Specific algorithms for 10/12 digit formats

370

371

### Common Validation Patterns

372

373

```python

374

import validators

375

376

# Batch validation example

377

identifiers = [

378

('ES', 'NIF', '12345678Z'),

379

('FI', 'SSN', '311280-999J'),

380

('IN', 'PAN', 'ABCDE1234F'),

381

('RU', 'INN', '1234567890'),

382

]

383

384

for country, type_name, id_value in identifiers:

385

# Try to validate based on country and type

386

is_valid = False

387

388

if country == 'ES' and type_name == 'NIF':

389

is_valid = bool(validators.es_nif(id_value))

390

elif country == 'FI' and type_name == 'SSN':

391

is_valid = bool(validators.fi_ssn(id_value))

392

elif country == 'IN' and type_name == 'PAN':

393

is_valid = bool(validators.ind_pan(id_value))

394

elif country == 'RU' and type_name == 'INN':

395

is_valid = bool(validators.ru_inn(id_value))

396

397

print(f"{country} {type_name} {id_value}: {'✓' if is_valid else '✗'}")

398

```