Crate langcodec

Crate langcodec 

Source
Expand description

Universal localization file toolkit for Rust.

Supports parsing, writing, and converting between Apple .strings, .xcstrings, Android strings.xml, and CSV files.
All conversion happens through the unified Resource model.

§Quick Start

use langcodec::{Codec, convert_auto};

// Convert between formats automatically
convert_auto("en.lproj/Localizable.strings", "strings.xml")?;

// Or work with the unified Resource model
let mut codec = Codec::new();
codec.read_file_by_extension("en.lproj/Localizable.strings", None)?;
codec.write_to_file()?;

// Or use the builder pattern for fluent construction
let codec = Codec::builder()
    .add_file("en.lproj/Localizable.strings")?
    .add_file("fr.lproj/Localizable.strings")?
    .add_file("values-es/strings.xml")?
    .read_file_by_extension("de.strings", Some("de".to_string()))?
    .build();

§Supported Formats

  • Apple .strings: Traditional iOS/macOS localization files
  • Apple .xcstrings: Modern Xcode localization format with plural support
  • Android strings.xml: Android resource files
  • CSV: Comma-separated values for simple key-value pairs

§Features

  • ✨ Parse, write, convert, and merge multiple localization file formats
  • 🦀 Idiomatic, modular, and ergonomic Rust API
  • 📦 Designed for CLI tools, CI/CD pipelines, and library integration
  • 🔄 Unified internal model (Resource) for lossless format-agnostic processing
  • 📖 Well-documented, robust error handling and extensible codebase

§Examples

§Basic Format Conversion

use langcodec::convert_auto;

// Convert Apple .strings to Android XML
convert_auto("en.lproj/Localizable.strings", "values-en/strings.xml")?;

// Convert to CSV for analysis
convert_auto("Localizable.xcstrings", "translations.csv")?;

§Working with Resources

use langcodec::{Codec, types::Entry};

// Load multiple files with the builder pattern
let codec = Codec::builder()
    .add_file("en.lproj/Localizable.strings")?
    .add_file("fr.lproj/Localizable.strings")?
    .add_file("values-es/strings.xml")?
    .build();

// Find specific translations
if let Some(en_resource) = codec.get_by_language("en") {
    if let Some(entry) = en_resource.entries.iter().find(|e| e.id == "welcome") {
        println!("Welcome message: {}", entry.value);
    }
}

§Modifying Translations

use langcodec::{Codec, types::{Translation, EntryStatus}};

let mut codec = Codec::builder()
    .add_file("en.lproj/Localizable.strings")?
    .add_file("fr.lproj/Localizable.strings")?
    .build();

// Update an existing translation
codec.update_translation(
    "welcome_message",
    "en",
    Translation::Singular("Hello, World!".to_string()),
    Some(EntryStatus::Translated)
)?;

// Add a new translation
codec.add_entry(
    "new_feature",
    "en",
    Translation::Singular("Check out our new feature!".to_string()),
    Some("Promotional message for new feature".to_string()),
    Some(EntryStatus::New)
)?;

// Copy a translation from one language to another
codec.copy_entry("welcome_message", "en", "fr", true)?;

// Find all translations for a key
for (resource, entry) in codec.find_entries("welcome_message") {
    println!("{}: {}", resource.metadata.language, entry.value);
}

// Validate the codec
if let Err(validation_error) = codec.validate() {
    eprintln!("Validation failed: {}", validation_error);
}

§Batch Processing

use langcodec::Codec;
use std::path::Path;

let mut codec = Codec::new();

// Load all localization files in a directory
for entry in std::fs::read_dir("locales")? {
    let path = entry?.path();
    if path.extension().and_then(|s| s.to_str()) == Some("strings") {
        codec.read_file_by_extension(&path, None)?;
    }
}

// Write all resources back to their original formats
codec.write_to_file()?;

Re-exports§

pub use crate::builder::CodecBuilder;
pub use crate::codec::Codec;
pub use crate::converter::convert;
pub use crate::converter::convert_auto;
pub use crate::converter::convert_auto_with_normalization;
pub use crate::converter::convert_resources_to_format;
pub use crate::converter::convert_with_normalization;
pub use crate::converter::infer_format_from_extension;
pub use crate::converter::infer_format_from_path;
pub use crate::converter::infer_language_from_path;
pub use crate::converter::merge_resources;
pub use crate::error::Error;
pub use crate::formats::FormatType;
pub use crate::placeholder::extract_placeholders;
pub use crate::placeholder::normalize_placeholders;
pub use crate::placeholder::signature;
pub use crate::plural_rules::PluralValidationReport;
pub use crate::plural_rules::autofix_fill_missing_from_other_resource;
pub use crate::plural_rules::collect_resource_plural_issues;
pub use crate::plural_rules::required_categories_for_str;
pub use crate::plural_rules::validate_resource_plurals;
pub use crate::types::ConflictStrategy;
pub use crate::types::Entry;
pub use crate::types::EntryStatus;
pub use crate::types::Metadata;
pub use crate::types::Plural;
pub use crate::types::PluralCategory;
pub use crate::types::Resource;
pub use crate::types::Translation;

Modules§

builder
codec
converter
Format conversion utilities for langcodec.
error
All error types for the langcodec crate.
formats
All supported localization file formats for langcodec.
placeholder
Placeholder parsing, normalization and validation utilities.
plural_rules
traits
Traits for format-agnostic parsing and serialization in langcodec.
types
Core, format-agnostic types for langcodec. Parsers decode into these; encoders serialize these.