db65db6232
Android UI Tests / ui-tests (push) Has been cancelled
Localize all user-facing strings across iOS (SwiftUI), shared Kotlin, and Android Compose into en/es/fr/de/pt/it/ja/ko/nl/zh: - iOS String Catalogs: main + widget Localizable.xcstrings, InfoPlist.xcstrings (permissions), plural variations, ~200 new keys translated - Shared Kotlin ClientStrings table + Android composeResources/values-* (884 keys ×10), routed Api/ViewModel/util error & UI strings through localization - Backend-localized lookups/suggestions consumed via display names - Widget extension catalog; theme names, home-profile fallbacks, validation, network errors, accessibility labels all localized Add re-runnable verification gates: - scripts/i18n_audit.py — enumerate every literal, partition to GAP=0 - scripts/i18n_coverage.py — all 10 locales translated, format-specifier parity Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
172 lines
5.1 KiB
Kotlin
172 lines
5.1 KiB
Kotlin
package com.tt.honeyDue.models
|
|
|
|
import kotlinx.serialization.SerialName
|
|
import kotlinx.serialization.Serializable
|
|
|
|
/**
|
|
* Residence type lookup - matching Go API
|
|
* Note: Go API returns arrays directly, no wrapper
|
|
*/
|
|
@Serializable
|
|
data class ResidenceType(
|
|
val id: Int,
|
|
val name: String,
|
|
@SerialName("display_name") val displayNameLocalized: String = ""
|
|
) {
|
|
/** Localized label for the current locale; falls back to [name]. */
|
|
val displayName: String
|
|
get() = displayNameLocalized.ifBlank { name }
|
|
}
|
|
|
|
/**
|
|
* Task frequency lookup - matching Go API TaskFrequencyResponse
|
|
*/
|
|
@Serializable
|
|
data class TaskFrequency(
|
|
val id: Int,
|
|
val name: String,
|
|
@SerialName("display_name") val displayNameLocalized: String = "",
|
|
val days: Int? = null,
|
|
@SerialName("display_order") val displayOrder: Int = 0
|
|
) {
|
|
/** Localized label for the current locale; falls back to [name]. */
|
|
val displayName: String
|
|
get() = displayNameLocalized.ifBlank { name }
|
|
}
|
|
|
|
/**
|
|
* Task priority lookup - matching Go API TaskPriorityResponse
|
|
*/
|
|
@Serializable
|
|
data class TaskPriority(
|
|
val id: Int,
|
|
val name: String,
|
|
@SerialName("display_name") val displayNameLocalized: String = "",
|
|
val level: Int = 0,
|
|
val color: String = "",
|
|
@SerialName("display_order") val displayOrder: Int = 0
|
|
) {
|
|
/** Localized label for the current locale; falls back to [name]. */
|
|
val displayName: String
|
|
get() = displayNameLocalized.ifBlank { name }
|
|
}
|
|
|
|
/**
|
|
* Task category lookup - matching Go API TaskCategoryResponse
|
|
*/
|
|
@Serializable
|
|
data class TaskCategory(
|
|
val id: Int,
|
|
val name: String,
|
|
@SerialName("display_name") val displayNameLocalized: String = "",
|
|
val description: String = "",
|
|
val icon: String = "",
|
|
val color: String = "",
|
|
@SerialName("display_order") val displayOrder: Int = 0
|
|
) {
|
|
/** Localized label for the current locale; falls back to [name]. */
|
|
val displayName: String
|
|
get() = displayNameLocalized.ifBlank { name }
|
|
}
|
|
|
|
/**
|
|
* Contractor specialty lookup
|
|
*/
|
|
@Serializable
|
|
data class ContractorSpecialty(
|
|
val id: Int,
|
|
val name: String,
|
|
@SerialName("display_name") val displayNameLocalized: String = "",
|
|
val description: String? = null,
|
|
val icon: String? = null,
|
|
@SerialName("display_order") val displayOrder: Int = 0
|
|
) {
|
|
/** Localized label for the current locale; falls back to [name]. */
|
|
val displayName: String
|
|
get() = displayNameLocalized.ifBlank { name }
|
|
}
|
|
|
|
/**
|
|
* A selectable home-profile field option (heating type, roof type, etc.),
|
|
* served localized by the backend. [value] is the stable code stored on the
|
|
* residence; [displayName] is the localized label.
|
|
*/
|
|
@Serializable
|
|
data class HomeProfileOption(
|
|
val value: String,
|
|
@SerialName("display_name") val displayName: String
|
|
)
|
|
|
|
/**
|
|
* Minimal contractor info for task references
|
|
*/
|
|
@Serializable
|
|
data class ContractorMinimal(
|
|
val id: Int,
|
|
val name: String,
|
|
val company: String? = null
|
|
)
|
|
|
|
/**
|
|
* Static data response - all lookups in one call
|
|
* Note: This may need adjustment based on Go API implementation
|
|
*/
|
|
@Serializable
|
|
data class StaticDataResponse(
|
|
@SerialName("residence_types") val residenceTypes: List<ResidenceType>,
|
|
@SerialName("task_frequencies") val taskFrequencies: List<TaskFrequency>,
|
|
@SerialName("task_priorities") val taskPriorities: List<TaskPriority>,
|
|
@SerialName("task_categories") val taskCategories: List<TaskCategory>,
|
|
@SerialName("contractor_specialties") val contractorSpecialties: List<ContractorSpecialty>
|
|
)
|
|
|
|
/**
|
|
* Unified seeded data response - all lookups + task templates in one call
|
|
* Supports ETag-based conditional fetching for efficient caching
|
|
*/
|
|
@Serializable
|
|
data class SeededDataResponse(
|
|
@SerialName("residence_types") val residenceTypes: List<ResidenceType>,
|
|
@SerialName("task_categories") val taskCategories: List<TaskCategory>,
|
|
@SerialName("task_priorities") val taskPriorities: List<TaskPriority>,
|
|
@SerialName("task_frequencies") val taskFrequencies: List<TaskFrequency>,
|
|
@SerialName("contractor_specialties") val contractorSpecialties: List<ContractorSpecialty>,
|
|
@SerialName("task_templates") val taskTemplates: TaskTemplatesGroupedResponse,
|
|
@SerialName("home_profile_options") val homeProfileOptions: Map<String, List<HomeProfileOption>> = emptyMap(),
|
|
@SerialName("document_types") val documentTypes: List<HomeProfileOption> = emptyList(),
|
|
@SerialName("document_categories") val documentCategories: List<HomeProfileOption> = emptyList()
|
|
)
|
|
|
|
// Legacy wrapper responses for backward compatibility
|
|
// These can be removed once all code is migrated to use arrays directly
|
|
|
|
@Serializable
|
|
data class ResidenceTypeResponse(
|
|
val count: Int,
|
|
val results: List<ResidenceType>
|
|
)
|
|
|
|
@Serializable
|
|
data class TaskFrequencyResponse(
|
|
val count: Int,
|
|
val results: List<TaskFrequency>
|
|
)
|
|
|
|
@Serializable
|
|
data class TaskPriorityResponse(
|
|
val count: Int,
|
|
val results: List<TaskPriority>
|
|
)
|
|
|
|
@Serializable
|
|
data class TaskCategoryResponse(
|
|
val count: Int,
|
|
val results: List<TaskCategory>
|
|
)
|
|
|
|
@Serializable
|
|
data class ContractorSpecialtyResponse(
|
|
val count: Int,
|
|
val results: List<ContractorSpecialty>
|
|
)
|