Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ HumanReadable.timeAgo(instant) // "il y a 3 jours"

### Supported languages

* Arabic
* Czech
* Chinese (since 1.3.0)
* Dutch
Expand Down
5 changes: 5 additions & 0 deletions demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ kotlin {
binaries.executable()
}

jvm()

sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
Expand All @@ -32,6 +34,9 @@ kotlin {
implementation(libs.kotlinX.datetime)
implementation(rootProject)
}
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
}
}
}

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
internal enum class Language(val code: String) {
English("en"),
Arabic("ar"),
Czech("cs"),
Chinese("zh"),
Dutch("nl"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import monoBodyOrange
Expand Down Expand Up @@ -91,7 +92,9 @@ internal fun AbbreviationDemo(
append("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import monoBodyOrange
Expand Down Expand Up @@ -108,7 +109,9 @@ internal fun DistanceDemo(
append("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import monoBodyOrange
Expand Down Expand Up @@ -97,7 +98,9 @@ internal fun FileSizeDemo(
append("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import monoBodyOrange
Expand Down Expand Up @@ -92,7 +93,9 @@ internal fun NumberFormatDemo(
append("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import kotlinx.datetime.*
Expand Down Expand Up @@ -85,7 +86,9 @@ internal fun TimeDemo(
appendLine("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
Text(
text = buildAnnotatedString {
Expand All @@ -96,7 +99,9 @@ internal fun TimeDemo(
append("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
Spacer(Modifier.height(16.dp))

Expand All @@ -111,7 +116,9 @@ internal fun TimeDemo(
append("\"")
}
},
style = monoBody
style = monoBody.copy(
textDirection = if (selectedLanguageCode == "ar") TextDirection.Rtl else TextDirection.Ltr
)
)
}
}
Expand Down
10 changes: 10 additions & 0 deletions demo/src/jvmMain/kotlin/main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

fun main() = application {
Window(
onCloseRequest = ::exitApplication,
) {
App()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,15 @@ internal actual fun extendLibresPlurals() {
else -> PluralForm.Other
}
}

PluralRules["ar"] = PluralRule { number ->
when {
number == 0 -> PluralForm.Zero
number == 1 -> PluralForm.One
number == 2 -> PluralForm.Two
number % 100 in 3..10 -> PluralForm.Few
number % 100 in 11..99 -> PluralForm.Many
else -> PluralForm.Other
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nl.jacobras.humanreadable

import io.github.skeptick.libres.LibresSettings
import kotlin.math.roundToInt
import kotlin.time.Duration

Expand All @@ -17,7 +18,7 @@ internal fun formatDuration(
val monthsAgo = (duration.inWholeDays / 30.5f).roundToInt()
val yearsAgo = (duration.inWholeDays / 365).toInt()

return when {
val result = when {
secondsAgo < 60 -> {
"$secondsAgo ${TimeUnit.Seconds.format(secondsAgo, relativeTime)}"
}
Expand All @@ -41,4 +42,10 @@ internal fun formatDuration(
"$yearsAgo ${TimeUnit.Years.format(yearsAgo, relativeTime)}"
}
}

return if (LibresSettings.languageCode == "ar" && (result.startsWith("1 ") || result.startsWith("2 "))) {
result.substringAfter(" ")
} else {
result
}
}
8 changes: 8 additions & 0 deletions src/commonMain/libres/strings/data_units_ar.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="byte_symbol">ب</string>
<string name="kilobyte_symbol">ك.ب</string>
<string name="megabyte_symbol">م.ب</string>
<string name="gigabyte_symbol">ج.ب</string>
<string name="terabyte_symbol">ت.ب</string>
</resources>
7 changes: 7 additions & 0 deletions src/commonMain/libres/strings/distance_units_ar.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="meter_abbreviation">م</string>
<string name="kilometer_abbreviation">كم</string>
<string name="feet_abbreviation">قدم</string>
<string name="mile_abbreviation">ميل</string>
</resources>
111 changes: 111 additions & 0 deletions src/commonMain/libres/strings/time_units_ar.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="seconds">
<item quantity="zero">ثانية</item>
<item quantity="one">ثانية</item>
<item quantity="two">ثانيتان</item>
<item quantity="few">ثوان</item>
<item quantity="many">ثانية</item>
<item quantity="other">ثانية</item>
</plurals>
<plurals name="seconds_past">
<item quantity="two">ثانيتين</item>
</plurals>
<plurals name="seconds_future">
<item quantity="two">ثانيتين</item>
</plurals>

<plurals name="minutes">
<item quantity="zero">دقيقة</item>
<item quantity="one">دقيقة</item>
<item quantity="two">دقيقتان</item>
<item quantity="few">دقائق</item>
<item quantity="many">دقيقة</item>
<item quantity="other">دقيقة</item>
</plurals>
<plurals name="minutes_past">
<item quantity="two">دقيقتين</item>
</plurals>
<plurals name="minutes_future">
<item quantity="two">دقيقتين</item>
</plurals>

<plurals name="hours">
<item quantity="zero">ساعة</item>
<item quantity="one">ساعة</item>
<item quantity="two">ساعتان</item>
<item quantity="few">ساعات</item>
<item quantity="many">ساعة</item>
<item quantity="other">ساعة</item>
</plurals>
<plurals name="hours_past">
<item quantity="two">ساعتين</item>
</plurals>
<plurals name="hours_future">
<item quantity="two">ساعتين</item>
</plurals>

<plurals name="days">
<item quantity="zero">يوم</item>
<item quantity="one">يوم</item>
<item quantity="two">يومان</item>
<item quantity="few">أيام</item>
<item quantity="many">يوم</item>
<item quantity="other">يوم</item>
</plurals>
<plurals name="days_past">
<item quantity="two">يومين</item>
</plurals>
<plurals name="days_future">
<item quantity="two">يومين</item>
</plurals>

<plurals name="weeks">
<item quantity="zero">أسبوع</item>
<item quantity="one">أسبوع</item>
<item quantity="two">أسبوعان</item>
<item quantity="few">أسابيع</item>
<item quantity="many">أسبوع</item>
<item quantity="other">أسبوع</item>
</plurals>
<plurals name="weeks_past">
<item quantity="two">أسبوعين</item>
</plurals>
<plurals name="weeks_future">
<item quantity="two">أسبوعين</item>
</plurals>

<plurals name="months">
<item quantity="zero">شهر</item>
<item quantity="one">شهر</item>
<item quantity="two">شهران</item>
<item quantity="few">أشهر</item>
<item quantity="many">شهر</item>
<item quantity="other">شهر</item>
</plurals>
<plurals name="months_past">
<item quantity="two">شهرين</item>
</plurals>
<plurals name="months_future">
<item quantity="two">شهرين</item>
</plurals>

<plurals name="years">
<item quantity="zero">سنة</item>
<item quantity="one">سنة</item>
<item quantity="two">سنتان</item>
<item quantity="few">سنوات</item>
<item quantity="many">سنة</item>
<item quantity="other">سنة</item>
</plurals>
<plurals name="years_past">
<item quantity="two">سنتين</item>
</plurals>
<plurals name="years_future">
<item quantity="two">سنتين</item>
</plurals>

<string name="time_ago">قبل ${time}</string>
<string name="time_in_future">بعد ${time}</string>
<string name="now">الآن</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,32 @@ class LocalizedTests {
private val oneYearAgo = now - oneYear
private val oneYearFromNow = now + oneYear

@Test
fun ar_arabic() {
LibresSettings.languageCode = "ar"
assertThat(HumanReadable.duration(0.seconds)).isEqualTo("0 ثانية")
assertThat(HumanReadable.duration(1.seconds)).isEqualTo("ثانية")
assertThat(HumanReadable.duration(2.seconds)).isEqualTo("ثانيتان")
assertThat(HumanReadable.duration(3.seconds)).isEqualTo("3 ثوان")
assertThat(HumanReadable.duration(11.seconds)).isEqualTo("11 ثانية")

assertThat(HumanReadable.timeAgo(now)).isEqualTo("الآن")
assertThat(HumanReadable.timeAgo(twoSecondsAgo, baseInstant = now)).isEqualTo("قبل ثانيتين")
assertThat(HumanReadable.timeAgo(oneMinuteFromNow, baseInstant = now)).isEqualTo("بعد دقيقة")
assertThat(HumanReadable.duration(3.days)).isEqualTo("3 أيام")
assertThat(HumanReadable.duration(twoMonths)).isEqualTo("شهران")
assertThat(HumanReadable.duration(oneYear)).isEqualTo("سنة")

assertThat(HumanReadable.number(1_000_000.34, decimals = 2)).isEqualTo("1,000,000.34")
assertThat(HumanReadable.number(-4.34, decimals = 2)).isEqualTo("-4.34")

assertThat(HumanReadable.fileSize(2_000_000, decimals = 1)).isEqualTo("1.9 م.ب")

assertThat(HumanReadable.abbreviation(5_100_000, decimals = 1)).isEqualTo("5.1M")

assertThat(HumanReadable.distance(7234, unit = DistanceUnit.Meter)).isEqualTo("7.2 كم")
}

@Test
fun cs_czech() {
LibresSettings.languageCode = "cs"
Expand Down Expand Up @@ -307,4 +333,4 @@ class LocalizedTests {
assertThat(HumanReadable.number(1_000_000.34, decimals = 2)).isEqualTo("1,000,000.34")
assertThat(HumanReadable.number(-4.34, decimals = 2)).isEqualTo("-4.34")
}
}
}