Expand description
Universal localization file toolkit for Rust.
Supports parsing, writing, and converting between Apple .strings, .stringsdict,
.xcstrings, .xliff, Android strings.xml, CSV, and TSV 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
.stringsdict: XML and binary input plus canonical XML output for one bare plural selector - Apple
.xcstrings: Modern Xcode localization format with plural support - Apple
.xliff: Xcode localization exchange files (XLIFF 1.2) - Android
strings.xml: Android resource files - CSV: Conventional wide data plus an automatic versioned schema for lossless model data
- TSV: Conventional wide data plus the same automatic versioned schema
§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) with explicit errors for non-representable output - 📖 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::error::ErrorCode;pub use crate::error::ErrorContext;pub use crate::error::StructuredError;pub use crate::formats::FormatType;pub use crate::normalize::KeyStyle;pub use crate::normalize::NormalizeOptions;pub use crate::normalize::NormalizeReport;pub use crate::normalize::normalize_codec;pub use crate::operations::DiffChangedItem;pub use crate::operations::DiffOptions;pub use crate::operations::DiffReport;pub use crate::operations::DiffSummary;pub use crate::operations::LanguageDiff;pub use crate::operations::SyncIssue;pub use crate::operations::SyncIssueKind;pub use crate::operations::SyncOptions;pub use crate::operations::SyncReport;pub use crate::operations::diff_resources;pub use crate::operations::sync_existing_entries;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::provenance::PROVENANCE_PREFIX;pub use crate::provenance::ProvenanceRecord;pub use crate::provenance::entry_provenance;pub use crate::provenance::resource_provenance;pub use crate::provenance::set_entry_provenance;pub use crate::provenance::set_resource_provenance;pub use crate::read_options::ReadOptions;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.
- normalize
- operations
- High-level resource operations (sync/diff) reusable by CLI and library users.
- placeholder
- Placeholder parsing, normalization and validation utilities.
- plural_
rules - provenance
- Helpers for attaching and reading provenance metadata.
- read_
options - Options for strict/controlled file reading into
Resource. - traits
- Traits for format-agnostic parsing and serialization in langcodec.
- types
- Core, format-agnostic types for langcodec. Parsers decode into these; encoders serialize these.