Add comprehensive i18n localization for KMM and iOS

KMM (Android/Shared):
- Add strings.xml with 200+ localized strings
- Add translation files for es, fr, de, pt languages
- Update all screens to use stringResource() for i18n
- Add Accept-Language header to API client for all platforms

iOS:
- Add L10n.swift helper with type-safe string accessors
- Add Localizable.xcstrings with translations for all 5 languages
- Update all SwiftUI views to use L10n.* for localized strings
- Localize Auth, Residence, Task, Contractor, Document, and Profile views

Supported languages: English, Spanish, French, German, Portuguese

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-02 02:02:00 -06:00
parent e62e7d4371
commit c726320c1e
59 changed files with 19839 additions and 757 deletions

View File

@@ -21,11 +21,11 @@ struct CompletionHistorySheet: View {
completionsList
}
}
.navigationTitle("Completion History")
.navigationTitle(L10n.Tasks.completionHistory)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Done") {
Button(L10n.Common.done) {
isPresented = false
}
}
@@ -47,7 +47,7 @@ struct CompletionHistorySheet: View {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: Color.appPrimary))
.scaleEffect(1.5)
Text("Loading completions...")
Text(L10n.Tasks.loadingCompletions)
.font(.subheadline)
.foregroundColor(Color.appTextSecondary)
}
@@ -60,7 +60,7 @@ struct CompletionHistorySheet: View {
.font(.system(size: 48))
.foregroundColor(Color.appError)
Text("Failed to load completions")
Text(L10n.Tasks.failedToLoad)
.font(.headline)
.foregroundColor(Color.appTextPrimary)
@@ -73,7 +73,7 @@ struct CompletionHistorySheet: View {
Button(action: {
viewModel.loadCompletions(taskId: taskId)
}) {
Label("Retry", systemImage: "arrow.clockwise")
Label(L10n.Common.retry, systemImage: "arrow.clockwise")
.foregroundColor(Color.appPrimary)
}
.padding(.top, AppSpacing.sm)
@@ -87,11 +87,11 @@ struct CompletionHistorySheet: View {
.font(.system(size: 48))
.foregroundColor(Color.appTextSecondary.opacity(0.5))
Text("No Completions Yet")
Text(L10n.Tasks.noCompletionsYet)
.font(.headline)
.foregroundColor(Color.appTextPrimary)
Text("This task has not been completed.")
Text(L10n.Tasks.notCompleted)
.font(.subheadline)
.foregroundColor(Color.appTextSecondary)
}
@@ -110,7 +110,7 @@ struct CompletionHistorySheet: View {
.fontWeight(.semibold)
.foregroundColor(Color.appTextPrimary)
Spacer()
Text("\(viewModel.completions.count) \(viewModel.completions.count == 1 ? "completion" : "completions")")
Text("\(viewModel.completions.count) \(viewModel.completions.count == 1 ? L10n.Tasks.completion : L10n.Tasks.completions)")
.font(.caption)
.foregroundColor(Color.appTextSecondary)
}
@@ -146,7 +146,7 @@ struct CompletionHistoryCard: View {
HStack(spacing: 4) {
Image(systemName: "person.fill")
.font(.caption2)
Text("Completed by \(completedBy)")
Text("\(L10n.Tasks.completedByName) \(completedBy)")
.font(.caption)
}
.foregroundColor(Color.appTextSecondary)
@@ -213,7 +213,7 @@ struct CompletionHistoryCard: View {
// Notes
if !completion.notes.isEmpty {
VStack(alignment: .leading, spacing: 4) {
Text("Notes")
Text(L10n.Tasks.notes)
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(Color.appTextSecondary)
@@ -233,7 +233,7 @@ struct CompletionHistoryCard: View {
HStack {
Image(systemName: "photo.on.rectangle.angled")
.font(.subheadline)
Text("View Photos (\(completion.images.count))")
Text("\(L10n.Tasks.viewPhotos) (\(completion.images.count))")
.font(.subheadline)
.fontWeight(.semibold)
}