ukraine 1.1.0

Glory to Ukraine. Library for transliterating Ukrainian Cyrillic text into Latin script representation
Documentation
# Ukraine 🇺🇦

[![Crates.io](https://img.shields.io/crates/v/ukraine.svg)](https://crates.io/crates/ukraine)
[![Documentation](https://docs.rs/ukraine/badge.svg)](https://docs.rs/ukraine)
[![License: LGPL-3.0-only](https://img.shields.io/badge/License-LGPL--3.0--only-blue.svg)](LICENSE)

A Rust library for transliterating Ukrainian Cyrillic text into Latin-script representations. In the hope that one day the Ukrainian Latin script will be widely adopted and the last remnants of [russian aggressive imperialism](https://war.ukraine.ua/) will be erased from the history of modern Ukraine 💙💛

## Support Ukraine

[![United24](https://u24.gov.ua/assets/img/home/logo_white.svg)](https://u24.gov.ua/)

## Overview

This Rust crate provides functionality for converting Ukrainian Cyrillic text into various transliteration schemes described on the [Ukrainian Latin alphabet](https://en.m.wikipedia.org/wiki/Ukrainian_Latin_alphabet) page.

Currently supports the following transliteration systems from Ukrainian Cyrillic to Latin:

- **Lozynskyi's Abecadło** — A historical Ukrainian Latin alphabet proposal
- **DSTU 9112:2021 System A and B** — Official Ukrainian standard for Cyrillic-Latin transliteration [reference]https://en.wikipedia.org/wiki/DSTU_9112:2021
- **KMU #55 (2010)** — Ukrainian National transliteration system for romanization of geographic names. Resolution of the Cabinet of Ministers of Ukraine [reference]https://www.kmu.gov.ua/npas/243262567

This library is implemented in **pure Rust** with **zero dependencies** and **no regex**. All transliteration logic is built from scratch using native Rust string processing for maximum performance and minimal overhead.

## Features

- [x] ***Greeting:*** Say hello in various forms—formal or casual.
- [x] ***Ukrainian Transliteration:*** Convert Ukrainian text from Cyrillic to Latin script.
- [x] ***Number Conversion:*** Convert numbers into Ukrainian words.
- [x] ***Ordinal Number Conversion:*** Convert integers into Ukrainian ordinal words.
- [x] ***Date and Time Conversion:*** Format dates and times according to Ukrainian standards.
- [ ] ***Counting Endings:*** Properly display singular and plural forms.
- [ ] ***Feminization:*** Convert masculine forms to feminine forms and vice versa.
- [ ] ***Currency Formatting:*** Convert numerical currency values into Ukrainian words.
- [ ] ***Name generation:*** Generate placeholder names for persons, cities, and companies.
- [ ] ***Address Conversion:*** Convert addresses to Ukrainian standards.
- [ ] ***Phone Number Formatting:*** Convert phone numbers to Ukrainian standards.

## Installation

Add the following line to your `Cargo.toml` dependencies:

```toml
[dependencies]
ukraine = "1"
```

## Examples

### Say "Hello" in Ukrainian

```rust
// ukraine = { version = "1", default-features = false, features = ["greeting"] }

use ukraine::greeting::vitayu;

fn main() {
    println!("{}", vitayu()); // Вітаю
}
```

### DSTU 9112:2021 System A (ДСТУ 9112:2021)

Cyrillic-Latin transliteration of Ukrainian texts

[DSTU 9112](https://en.wikipedia.org/wiki/DSTU_9112:2021)

```rust
// ukraine = { version = "1", default-features = false, features = ["dstu9112a"] }
use ukraine::latin::transliterate_dstu9112a;

fn main() {
    assert_eq!(transliterate_dstu9112a("Привіт"), "Pryvit");
    assert_eq!(transliterate_dstu9112a("Житомир"), "Žytomyr");
    assert_eq!(transliterate_dstu9112a("Запоріжжя"), "Zaporižžja");
    assert_eq!(transliterate_dstu9112a("Київ"), "Kyïv");
    assert_eq!(transliterate_dstu9112a("Ужгород"), "Užğorod");
    assert_eq!(transliterate_dstu9112a("Черкаси"), "Čerkasy");
    assert_eq!(transliterate_dstu9112a("Чернівці"), "Černivci");
    assert_eq!(transliterate_dstu9112a("Чернігів"), "Černiğiv");
    assert_eq!(transliterate_dstu9112a("Україна"), "Ukraïna");
}
```

### DSTU 9112:2021 System B (ДСТУ 9112:2021)

Cyrillic-Latin transliteration of Ukrainian texts

[DSTU 9112](https://en.wikipedia.org/wiki/DSTU_9112:2021)

```rust
// ukraine = { version = "1", default-features = false, features = ["dstu9112b"] }
use ukraine::latin::transliterate_dstu9112b;

fn main() {
    let input = "Ще не вмерла України і слава, і воля,
Ще нам, браття молодії, усміхнеться доля.
Згинуть наші воріженьки, як роса на сонці.
Запануєм і ми, браття, у своїй сторонці.";
    let expected = "Shche ne vmerla Ukrajiny i slava, i volja,
Shche nam, brattja molodiji, usmikhnetjsja dolja.
Zghynutj nashi vorizhenjku, jak rosa na sonci.
Zapanujem i my, brattja, u svojij storonci.";
    assert_eq!(transliterate_dstu9112b(input), expected);
}
```

### Transliteration system approved by Cabinet of Ministers resolution #55 (2010 year)

[KMU №55](https://www.kmu.gov.ua/npas/243262567)

```rust
// ukraine = { version = "1", default-features = false, features = ["kmu55"] }

use ukraine::latin::transliterate_kmu55;

fn main() {
    assert_eq!(transliterate_kmu55("Київ"), "Kyiv");
    assert_eq!(transliterate_kmu55("Михайло"), "Mykhailo");
    assert_eq!(transliterate_kmu55("Юрій"), "Yurii");
    assert_eq!(transliterate_kmu55("Борщ"), "Borshch");
}
```

### Lozynskyi's abecadło

[Abecadło](https://en.wikipedia.org/wiki/Abecad%C5%82o)

```rust
// ukraine = { version = "1", default-features = false, features = ["lozynsky"] }

use ukraine::latin::transliterate_lozynsky;

fn main() {
    assert_eq!(transliterate_lozynsky("❤️ Україна"), "❤️ Ukrajina");
}
```

### Convert numbers into Ukrainian words

```rust
// ukraine = { version = "1", default-features = false, features = ["numbers"] }
use ukraine::numbers::{to_ordinal_words, to_words, OrdinalGender};

fn main() {
    assert_eq!(
        to_words(12_345_678),
        "дванадцять мільйонів триста сорок п'ять тисяч шістсот сімдесят вісім"
    );
}
```

### Convert numbers into Ukrainian ordinal words

```rust
// ukraine = { version = "1", default-features = false, features = ["numbers"] }

use ukraine::numbers::{to_ordinal_words, OrdinalGender};

fn main() {
    assert_eq!(to_ordinal_words(123, OrdinalGender::Feminine), "сто двадцять третя");
    assert_eq!(to_ordinal_words(123, OrdinalGender::Masculine), "сто двадцять третій");
    assert_eq!(to_ordinal_words(123, OrdinalGender::Neuter), "сто двадцять третє");
    assert_eq!(
        to_ordinal_words(21, OrdinalGender::Masculine),
        "двадцять перший"
    );
    assert_eq!(
        to_ordinal_words(45, OrdinalGender::Feminine),
        "сорок п'ята"
    );
}
```

### Format dates and times in Ukrainian

```rust
// ukraine = { version = "1", default-features = false, features = ["datetime"] }

use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use ukraine::datetime::{format_date, format_time, format_datetime, DateFormatStyle, FormatOptions};

fn main() {
    let independence_day = NaiveDate::from_ymd_opt(2024, 8, 24).unwrap();
    let ceremony = NaiveDateTime::new(
        independence_day,
        NaiveTime::from_hms_opt(9, 0, 0).unwrap(),
    );

    // Date format
    assert_eq!(
        format_date(independence_day, DateFormatStyle::Long),
        "24 серпня 2024 року"
    );

    // Full date time format
    assert_eq!(
        format_datetime(ceremony, FormatOptions::default()),
        "24 серпня 2024 року о 09:00"
    );

    // 12 hours
    let time = NaiveTime::from_hms_opt(8, 10, 59).unwrap();
    assert_eq!(
        format_time(time, TimeFormatStyle::TwelveHourNoSeconds),
        "08:10 ранку"
    );

    // 24 hours
    let time = NaiveTime::from_hms_opt(23, 59, 59).unwrap();
    assert_eq!(
        format_time(time, TimeFormatStyle::TwentyFourHour),
        "23:59:59"
    );

    // 24 hours no seconds
    let time = NaiveTime::from_hms_opt(23, 59, 59).unwrap();
    assert_eq!(
        format_time(time, TimeFormatStyle::TwentyFourHourNoSeconds),
        "23:59"
    );
}
```

```rust
// ukraine = { version = "1", default-features = false, features = ["numbers", "dstu9112a"] }

use ukraine::numbers::to_words;
use ukraine::latin::dstu9112a::transliterate_dstu9112a;

fn main() {
    assert_eq!(
        transliterate_dstu9112a(&to_words(12_345_678)),
        "dvanadcjatj miljjoniv trysta sorok p’jatj tysjač šistsot simdesjat visim"
    );
}
```

## Documentation

The full API documentation is available at [docs.rs/ukraine](https://docs.rs/ukraine).

## Alternative

Alternative crates for supporting DSTU 9112:2021 and KMU 55:2010: the [uklatn](https://crates.io/crates/uklatn) crate provides a solid regex-based implementation of these transliteration schemes.

## Contributing

Contributions are welcome! Please open an issue or submit a pull request for any improvements or bug fixes.