Skip to content

Validation ​

This page details the validation capabilities of the ally-bcp-47 library and how to use them.

Interactive Tag Builder

Language
en
Extended Language
+ Add Extended Language
Script
+ Add Script
Region
+ Add Region
Variant
+ Add Variant
Extension
+ Add Extension
Private Use
+ Add Private Use
en

Click on any part of the tag above to add or modify its value.

Only the language part is required. All others are optional.

Try Presets:

Validation Process ​

The library validates language tags in two key steps:

  1. Syntax Validation: Checks if the tag follows the BCP-47 syntax rules
  2. Registry Validation: Checks if the subtags exist in the official registries

Validation Options ​

The validateLanguageTag function accepts options to customize validation:

typescript
import { validateLanguageTag } from "ally-bcp-47";

const options = {
  checkRegistry: true, // Check subtags against registries
  warnOnDeprecated: true, // Generate warnings for deprecated subtags
  warnOnRedundantScript: true, // Generate warnings for redundant script subtags
};

const result = validateLanguageTag("en-US", options);

Available Options ​

OptionTypeDefaultDescription
checkRegistrybooleantrueWhether to validate subtags against registries (ISO 639, ISO 15924, ISO 3166)
warnOnDeprecatedbooleantrueWhether to generate warnings for deprecated subtags
warnOnRedundantScriptbooleantrueWhether to generate warnings for redundant script subtags

Validation Results ​

The validateLanguageTag function returns a detailed result object:

typescript
type ValidationResult = {
  isWellFormed: boolean; // Whether the tag follows BCP-47 syntax
  isValid: boolean; // Whether the tag is well-formed and all subtags exist
  tag?: LanguageTag; // Parsed tag (if well-formed)
  errors?: ValidationError[]; // Validation errors (if any)
  warnings?: ValidationWarning[]; // Validation warnings (if any)
};

Error Types ​

The library generates different types of validation errors:

typescript
export enum ValidationErrorType {
  MALFORMED_TAG = "malformed_tag", // General syntax error
  INVALID_SYNTAX = "invalid_syntax", // Specific syntax error
  UNKNOWN_SUBTAG = "unknown_subtag", // Subtag not in registry
  DUPLICATE_SUBTAG = "duplicate_subtag", // Subtag appears multiple times
  INVALID_ORDER = "invalid_order", // Subtags in wrong order
  UNKNOWN_SINGLETON = "unknown_singleton", // Unknown extension singleton
}

Warning Types ​

The library also generates warnings for issues that don't make a tag invalid:

typescript
export enum ValidationWarningType {
  DEPRECATED_SUBTAG = "deprecated_subtag", // Subtag is deprecated
  REDUNDANT_SCRIPT = "redundant_script", // Script is redundant
  DEPRECATED_EXTENSION = "deprecated_extension", // Extension is deprecated
}

Validation Examples ​

Basic Validation ​

typescript
import { validateLanguageTag } from "ally-bcp-47";

// Valid tag
const result = validateLanguageTag("en-US");
console.log(result.isValid); // true
console.log(result.isWellFormed); // true

// Invalid tag (syntax error)
const syntaxError = validateLanguageTag("en--US");
console.log(syntaxError.isWellFormed); // false
console.log(syntaxError.errors);
// [{
//   type: 'invalid_syntax',
//   message: 'Double hyphen is not allowed in language tags'
// }]

// Invalid tag (unknown subtag)
const registryError = validateLanguageTag("en-ZZ");
console.log(registryError.isValid); // false
console.log(registryError.isWellFormed); // true
console.log(registryError.errors);
// [{
//   type: 'unknown_subtag',
//   message: 'Unknown region subtag: ZZ',
//   subtag: 'ZZ',
//   subtagType: 'region'
// }]

Validation with Suggestions ​

The library provides suggestions for certain types of errors:

typescript
// Common typo for the UK
const ukResult = validateLanguageTag("en-UK");
console.log(ukResult.isValid); // false
console.log(ukResult.errors);
// [{
//   type: 'unknown_subtag',
//   message: 'Unknown region subtag: UK',
//   subtag: 'UK',
//   subtagType: 'region',
//   suggestedReplacement: 'GB'
// }]

// Common language code typo
const chResult = validateLanguageTag("ch-DE");
console.log(chResult.isValid); // false
console.log(chResult.errors);
// [{
//   type: 'unknown_subtag',
//   message: 'Unknown language subtag: ch',
//   subtag: 'ch',
//   subtagType: 'language',
//   suggestedReplacement: 'zh'
// }]

Syntax-Only Validation ​

If you only want to check if a tag follows the BCP-47 syntax (without registry validation):

typescript
// Using validateLanguageTag with options
const syntaxResult = validateLanguageTag("en-ZZ", { checkRegistry: false });
console.log(syntaxResult.isWellFormed); // true
console.log(syntaxResult.isValid); // true (because we disabled registry validation)

// Using the isWellFormed convenience function
import { isWellFormed } from "ally-bcp-47";
console.log(isWellFormed("en-ZZ")); // true

Registry-Only Validation ​

If you know a tag is syntactically valid and just want to check the registry:

typescript
import { validateTagAgainstRegistry } from "ally-bcp-47/registry";

const registryResult = validateTagAgainstRegistry({
  language: "en",
  region: "ZZ",
});

console.log(registryResult.valid); // false
console.log(registryResult.problems);
// [{
//   type: 'unknown_region',
//   message: 'Unknown region subtag: ZZ',
//   subtag: 'ZZ',
//   subtagType: 'region'
// }]

Convenience Functions ​

For simple validation cases, the library provides convenience functions:

typescript
import { isValid, isWellFormed } from "ally-bcp-47";

// Check if a tag is valid (both well-formed and registry-valid)
console.log(isValid("en-US")); // true
console.log(isValid("en-ZZ")); // false
console.log(isValid("en--US")); // false

// Check if a tag is well-formed (syntax only)
console.log(isWellFormed("en-US")); // true
console.log(isWellFormed("en-ZZ")); // true
console.log(isWellFormed("en--US")); // false

Next Steps ​

  • Parsing - Learn how to parse language tags into their components
  • Canonicalization - Learn how to normalize language tags

Powered by Allyship.dev