diff --git a/feature/leave/src/main/kotlin/app/worktrack/feature/leave/LeaveTypeNames.kt b/feature/leave/src/main/kotlin/app/worktrack/feature/leave/LeaveTypeNames.kt
new file mode 100644
index 0000000..b3fbe7e
--- /dev/null
+++ b/feature/leave/src/main/kotlin/app/worktrack/feature/leave/LeaveTypeNames.kt
@@ -0,0 +1,15 @@
+package app.worktrack.feature.leave
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import app.worktrack.core.model.LeaveType
+
+/** Only the untouched Dari names signup seeds are translated; a company's own name stays as typed. */
+internal fun builtInNameRes(type: LeaveType): Int? = when {
+ type.code == "ANNUAL" && type.name == "رخصتی سالانه" -> R.string.leave_type_annual
+ type.code == "SICK" && type.name == "رخصتی مریضی" -> R.string.leave_type_sick
+ else -> null
+}
+
+@Composable
+internal fun LeaveType.displayName(): String = builtInNameRes(this)?.let { stringResource(it) } ?: name
diff --git a/feature/leave/src/main/kotlin/app/worktrack/feature/leave/apply/ApplyLeaveScreen.kt b/feature/leave/src/main/kotlin/app/worktrack/feature/leave/apply/ApplyLeaveScreen.kt
index fe9829a..d1ebd2d 100644
--- a/feature/leave/src/main/kotlin/app/worktrack/feature/leave/apply/ApplyLeaveScreen.kt
+++ b/feature/leave/src/main/kotlin/app/worktrack/feature/leave/apply/ApplyLeaveScreen.kt
@@ -42,6 +42,7 @@ import app.worktrack.core.designsystem.l10n.formatShamsiDate
import app.worktrack.core.designsystem.l10n.localizedDigits
import app.worktrack.core.designsystem.l10n.localizedMessage
import app.worktrack.feature.leave.R
+import app.worktrack.feature.leave.displayName
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
@@ -72,7 +73,7 @@ fun ApplyLeaveRoute(
) { padding ->
ApplyLeaveScreen(
state = state,
- typeNames = types.associate { it.id to it.name },
+ typeNames = types.associate { it.id to it.displayName() },
onTypeSelect = viewModel::onTypeSelect,
onStartDate = viewModel::onStartDate,
onEndDate = viewModel::onEndDate,
diff --git a/feature/leave/src/main/kotlin/app/worktrack/feature/leave/overview/LeaveOverviewScreen.kt b/feature/leave/src/main/kotlin/app/worktrack/feature/leave/overview/LeaveOverviewScreen.kt
index 57ba0c6..28b70f7 100644
--- a/feature/leave/src/main/kotlin/app/worktrack/feature/leave/overview/LeaveOverviewScreen.kt
+++ b/feature/leave/src/main/kotlin/app/worktrack/feature/leave/overview/LeaveOverviewScreen.kt
@@ -50,6 +50,7 @@ import app.worktrack.core.model.LeaveStatus
import app.worktrack.core.model.LeaveType
import app.worktrack.core.model.SyncStatus
import app.worktrack.feature.leave.R
+import app.worktrack.feature.leave.displayName
@Composable
fun LeaveOverviewRoute(
@@ -183,7 +184,7 @@ private fun BalanceRow(
color = MaterialTheme.colorScheme.primary,
)
Text(
- text = type?.name ?: stringResource(R.string.leave_generic_type),
+ text = type?.displayName() ?: stringResource(R.string.leave_generic_type),
style = MaterialTheme.typography.labelMedium,
)
if (balance.pendingDays > 0) {
@@ -220,7 +221,7 @@ private fun RequestCard(
Column(Modifier.weight(1f)) {
type?.let {
ColorDotChip(
- text = it.name,
+ text = it.displayName(),
dotColor = parseHexColor(it.colorHex),
)
}
diff --git a/feature/leave/src/main/res/values-en/strings.xml b/feature/leave/src/main/res/values-en/strings.xml
index 165a1da..bd97d08 100644
--- a/feature/leave/src/main/res/values-en/strings.xml
+++ b/feature/leave/src/main/res/values-en/strings.xml
@@ -48,4 +48,6 @@
Reason
Request approved
Request rejected
+ Annual leave
+ Sick leave
diff --git a/feature/leave/src/main/res/values-ps/strings.xml b/feature/leave/src/main/res/values-ps/strings.xml
index b60ae1f..4ef9f72 100644
--- a/feature/leave/src/main/res/values-ps/strings.xml
+++ b/feature/leave/src/main/res/values-ps/strings.xml
@@ -48,4 +48,6 @@
دلیل
غوښتنه تایید شوه
غوښتنه رد شوه
+ کلنۍ رخصتي
+ د ناروغۍ رخصتي
diff --git a/feature/leave/src/main/res/values/strings.xml b/feature/leave/src/main/res/values/strings.xml
index 1118336..ad9b372 100644
--- a/feature/leave/src/main/res/values/strings.xml
+++ b/feature/leave/src/main/res/values/strings.xml
@@ -48,4 +48,6 @@
دلیل
درخواست تایید شد
درخواست رد شد
+ رخصتی سالانه
+ رخصتی مریضی
diff --git a/feature/leave/src/test/kotlin/app/worktrack/feature/leave/LeaveTypeNamesTest.kt b/feature/leave/src/test/kotlin/app/worktrack/feature/leave/LeaveTypeNamesTest.kt
new file mode 100644
index 0000000..2d04bf2
--- /dev/null
+++ b/feature/leave/src/test/kotlin/app/worktrack/feature/leave/LeaveTypeNamesTest.kt
@@ -0,0 +1,27 @@
+package app.worktrack.feature.leave
+
+import app.worktrack.core.model.LeaveType
+import java.time.Instant
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+class LeaveTypeNamesTest {
+
+ private fun type(code: String, name: String) = LeaveType(
+ id = code.lowercase(), companyId = "c1", name = name, code = code, colorHex = "#000000",
+ isPaid = true, requiresAttachment = false, active = true, updatedAt = Instant.EPOCH,
+ )
+
+ @Test
+ fun builtInTypesWithTheSeededNameAreTranslated() {
+ assertEquals(R.string.leave_type_annual, builtInNameRes(type("ANNUAL", "رخصتی سالانه")))
+ assertEquals(R.string.leave_type_sick, builtInNameRes(type("SICK", "رخصتی مریضی")))
+ }
+
+ @Test
+ fun aNameTheCompanyTypedIsKept() {
+ assertNull(builtInNameRes(type("ANNUAL", "رخصتی تفریحی")))
+ assertNull(builtInNameRes(type("HAJJ", "رخصتی حج")))
+ }
+}
diff --git a/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/PayslipLineNames.kt b/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/PayslipLineNames.kt
new file mode 100644
index 0000000..eb29742
--- /dev/null
+++ b/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/PayslipLineNames.kt
@@ -0,0 +1,16 @@
+package app.worktrack.feature.payslips
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import app.worktrack.core.model.PayslipLine
+
+/** Payroll names these three lines in Dari itself; company components keep their own names. */
+internal fun builtInNameRes(line: PayslipLine): Int? = when (line.componentCode) {
+ "BASIC" -> R.string.pay_basic
+ "LOP" -> R.string.pay_absence
+ "TAX" -> R.string.pay_income_tax
+ else -> null
+}
+
+@Composable
+internal fun PayslipLine.displayName(): String = builtInNameRes(this)?.let { stringResource(it) } ?: componentName
diff --git a/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/detail/PayslipDetailScreen.kt b/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/detail/PayslipDetailScreen.kt
index 3af0129..41af2d1 100644
--- a/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/detail/PayslipDetailScreen.kt
+++ b/feature/payslips/src/main/kotlin/app/worktrack/feature/payslips/detail/PayslipDetailScreen.kt
@@ -30,6 +30,7 @@ import app.worktrack.core.designsystem.l10n.localizedDigits
import app.worktrack.core.model.PayComponentType
import app.worktrack.core.model.Payslip
import app.worktrack.feature.payslips.R
+import app.worktrack.feature.payslips.displayName
@Composable
fun PayslipDetailRoute(
@@ -99,11 +100,11 @@ private fun PayslipDetail(payslip: Payslip, modifier: Modifier = Modifier) {
if (earnings.isNotEmpty()) {
SectionHeader(stringResource(R.string.pay_earnings))
- LinesCard(lines = earnings.map { it.componentName to it.amount }, currency = payslip.currency)
+ LinesCard(lines = earnings.map { it.displayName() to it.amount }, currency = payslip.currency)
}
if (deductions.isNotEmpty()) {
SectionHeader(stringResource(R.string.pay_deductions))
- LinesCard(lines = deductions.map { it.componentName to it.amount }, currency = payslip.currency)
+ LinesCard(lines = deductions.map { it.displayName() to it.amount }, currency = payslip.currency)
}
SectionHeader(stringResource(R.string.pay_attendance_summary))
diff --git a/feature/payslips/src/main/res/values-en/strings.xml b/feature/payslips/src/main/res/values-en/strings.xml
index 057bcee..9904d1d 100644
--- a/feature/payslips/src/main/res/values-en/strings.xml
+++ b/feature/payslips/src/main/res/values-en/strings.xml
@@ -17,4 +17,7 @@
Loss-of-pay days
All months
No payslip for %1$s
+ Basic salary
+ Absence deduction
+ Income tax
diff --git a/feature/payslips/src/main/res/values-ps/strings.xml b/feature/payslips/src/main/res/values-ps/strings.xml
index c8281c2..fcd6385 100644
--- a/feature/payslips/src/main/res/values-ps/strings.xml
+++ b/feature/payslips/src/main/res/values-ps/strings.xml
@@ -17,4 +17,7 @@
د معاش کسر ورځې
ټولې میاشتې
د %1$s لپاره د معاش فیش نشته
+ اساسي معاش
+ د غیرحاضرۍ کسر
+ د معاش مالیه
diff --git a/feature/payslips/src/main/res/values/strings.xml b/feature/payslips/src/main/res/values/strings.xml
index 1654cf1..715cc6c 100644
--- a/feature/payslips/src/main/res/values/strings.xml
+++ b/feature/payslips/src/main/res/values/strings.xml
@@ -17,4 +17,7 @@
روزهای کسر معاش
همه ماهها
فیش معاشی برای %1$s نیست
+ معاش اساسی
+ کسر غیرحاضری
+ مالیهٔ معاش
diff --git a/feature/payslips/src/test/kotlin/app/worktrack/feature/payslips/PayslipLineNamesTest.kt b/feature/payslips/src/test/kotlin/app/worktrack/feature/payslips/PayslipLineNamesTest.kt
new file mode 100644
index 0000000..51a3a4e
--- /dev/null
+++ b/feature/payslips/src/test/kotlin/app/worktrack/feature/payslips/PayslipLineNamesTest.kt
@@ -0,0 +1,24 @@
+package app.worktrack.feature.payslips
+
+import app.worktrack.core.model.PayComponentType
+import app.worktrack.core.model.PayslipLine
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+class PayslipLineNamesTest {
+
+ private fun line(code: String, name: String) = PayslipLine(code, name, PayComponentType.EARNING, 1.0)
+
+ @Test
+ fun payrollWrittenLinesAreTranslated() {
+ assertEquals(R.string.pay_basic, builtInNameRes(line("BASIC", "معاش اساسی")))
+ assertEquals(R.string.pay_absence, builtInNameRes(line("LOP", "کسر غیرحاضری")))
+ assertEquals(R.string.pay_income_tax, builtInNameRes(line("TAX", "مالیهٔ معاش")))
+ }
+
+ @Test
+ fun companyComponentsKeepTheirName() {
+ assertNull(builtInNameRes(line("TRANSPORT", "کمک ترانسپورت")))
+ }
+}