// lang_de.mbt — German number spelling (cardinal, year).
//
// German word order reverses the teens/tens: 41 = "einundvierzig"
// (one-and-forty). The unit "1" is "eins" when it stands alone as the final
// word, but "ein" when it leads "und" (einund...).
// Long-scale scale words. Index = group power.
///|
let de_scale_sing : Array[String] = [
"", "tausend", "Million", "Milliarde", "Billion", "Billiarde", "Trillion", "Trilliarde",
"Quadrillion",
]
///|
let de_scale_plur : Array[String] = [
"", "tausend", "Millionen", "Milliarden", "Billionen", "Billiarden", "Trillionen",
"Trilliarden", "Quadrillionen",
]
///|
pub fn lang_de() -> Lang {
{
variant: De,
zero: "null",
ones: [
"null", "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht",
"neun",
],
teens: [
"zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn",
"achtzehn", "neunzehn",
],
tens: [
"", "zehn", "zwanzig", "dreißig", "vierzig", "fünfzig", "sechzig", "siebzig",
"achtzig", "neunzig",
],
hundred: "hundert",
thousands: de_scale_plur,
negative: "minus",
decimal: "Komma",
comma_sep: false,
}
}
///|
fn Lang::de_unit(self : Lang, u : Int) -> String {
if u == 1 {
"ein"
} else {
self.ones[u]
}
}
///|
fn Lang::below100_de(self : Lang, r : Int) -> String {
if r < 10 {
// final unit "1" reads "eins"
return if r == 1 { "eins" } else { self.ones[r] }
}
if r < 20 {
return self.teens[r - 10]
}
let d = r / 10
let u = r % 10
if u == 0 {
return self.tens[d]
}
return self.de_unit(u) + "und" + self.tens[d]
}
///|
fn Lang::triple_de(self : Lang, t : Int) -> String {
if t == 0 {
return ""
}
let h = t / 100
let r = t % 100
if h == 0 {
return self.below100_de(r)
}
let hprefix = if h == 1 { "ein" } else { self.ones[h] }
let hs = hprefix + "hundert"
if r == 0 {
return hs
}
return hs + self.below100_de(r)
}
///|
fn Lang::cardinal_de(self : Lang, n : BigInt) -> String {
if n == BigInt::from_int(0) {
return self.zero
}
if !self.supports(n) {
return ""
}
let neg = n < BigInt::from_int(0)
let n = if neg { -n } else { n }
let groups = group3(n)
let words : Array[String] = []
let powers : Array[Int] = []
for i = 0; i < groups.length(); i = i + 1 {
let (triple, power) = groups[i]
let t = triple.to_int()
if t == 0 {
continue
}
let mut s = self.triple_de(t)
if power > 0 {
if power == 1 {
if t == 1 {
s = "eintausend"
} else {
s = s + "tausend"
}
} else if t == 1 {
s = "eine " + de_scale_sing[power]
} else {
s = s + " " + de_scale_plur[power]
}
}
words.push(s)
powers.push(power)
}
let mut out = ""
for k = 0; k < words.length(); k = k + 1 {
if k == 0 {
out = words[k]
} else {
let prev = powers[k - 1]
let cur = powers[k]
if cur >= 2 || prev >= 2 {
out = out + " " + words[k]
} else {
out = out + words[k]
}
}
}
if neg {
"minus " + out
} else {
out
}
}
///|
/// German year reading (e.g. 2024 -> "zwanzig vierundzwanzig").
pub fn year_de(n : BigInt) -> String {
if n < BigInt::from_int(1000) || n > BigInt::from_int(9999) {
return lang_de().cardinal_de(n)
}
let neg = n < BigInt::from_int(0)
let n = if neg { -n } else { n }
if n % BigInt::from_int(1000) == BigInt::from_int(0) {
return lang_de().cardinal_de(n)
}
let s = n.to_string()
let first = BigInt::from_string(s[0:2].to_owned()).to_int()
let second = BigInt::from_string(s[2:4].to_owned()).to_int()
if second == 0 {
return lang_de().cardinal_de(n)
}
let a = lang_de().cardinal_de(BigInt::from_int(first))
let b = lang_de().cardinal_de(BigInt::from_int(second))
if neg {
"minus " + a + " " + b
} else {
a + " " + b
}
}