feat(i18n): complete internationalization for iOS + watchOS across all views
Migrate every hardcoded Text("...") string to the L10n / LocalizedStringResource
type-safe key system with full en/fr/de/es translations (4 languages).
iOS changes (TabataGo target):
- Strings.swift: ~90 new L10n keys across 13 groups (action, tab, home, zone,
level, programs, programDetail, player, profile, settings, policy, paywall,
health, complete, activity, onboarding, goal)
- Localizable.xcstrings: 145 → 245+ keys with fr/de/es translations
- Model enums: FitnessLevel.label & FitnessGoal.label changed from String to
LocalizedStringResource, backed by L10n.level/goal keys
- Component param types changed to LocalizedStringResource: StatBadge,
SectionHeader, ProfileRow, PolicySection, CompletionStat, FeatureRow,
OnboardingHeader, PrimaryButton, SelectionCard
- All 18 view files updated: HomeTab, ActivityTab, ProgramsTab, ProfileTab,
MainTabView, SettingsView, PolicyViews, CompletionView, BodyZoneView,
ProgramDetailView, PaywallView, OnboardingView, PlayerView
Watch changes (TabataGoWatch target):
- New Localizable.xcstrings: 23 keys with en/fr/de/es (phase labels, idle
state, activity rings, complication strings)
- New WatchL10n.swift: type-safe enum (needs manual Xcode target membership)
- Updated: WatchPlayerView, WatchIdleView, WatchActivityView,
TabataGoComplication (inline LocalizedStringResource for widget target)
Both iOS and watchOS targets build with zero errors.
This commit is contained in:
207
tabatago-swift/TabataGoWatch/Resources/Localizable.xcstrings
Normal file
207
tabatago-swift/TabataGoWatch/Resources/Localizable.xcstrings
Normal file
@@ -0,0 +1,207 @@
|
||||
{
|
||||
"sourceLanguage" : "en",
|
||||
"strings" : {
|
||||
|
||||
"watch.phase.getReady" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "BEREIT" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "GET READY" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "LISTO" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "PRÊT" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.phase.warmUp" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "AUFWÄRMEN" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "WARM UP" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "CALENTAMIENTO" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "ÉCHAUFFEMENT" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.phase.work" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "ARBEIT" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "WORK" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "TRABAJO" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "TRAVAIL" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.phase.rest" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "PAUSE" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "REST" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "DESCANSO" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "REPOS" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.phase.break" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "PAUSE" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "BREAK" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "PAUSA" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "PAUSE" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.phase.coolDown" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "ABKÜHLEN" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "COOL DOWN" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "ENFRIAMIENTO" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "RÉCUPÉRATION" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.phase.done" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "FERTIG" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "DONE" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "HECHO" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "TERMINÉ" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.idle.startOnPhone" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Workout auf\ndeinem iPhone starten" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Start a workout\non your iPhone" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Inicia un entrenamiento\nen tu iPhone" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Démarrer un entraînement\nsur votre iPhone" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.idle.connected" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Verbunden" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Connected" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Conectado" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Connecté" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.idle.noPhone" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Kein Telefon" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "No phone" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Sin teléfono" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Pas de téléphone" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.activity.today" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Heute" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Today" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Hoy" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Aujourd'hui" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.activity.move" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Bewegung" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Move" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Mover" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Bouger" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.activity.exercise" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Sport" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Exercise" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Ejercicio" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Exercice" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.activity.stand" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Stehen" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Stand" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Estar de pie" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Debout" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.activity.streak" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Serie" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "streak" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "racha" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "série" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.notStarted" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Nicht begonnen" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Not started" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "No iniciado" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Pas commencé" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.today" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Heute" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Today" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Hoy" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Aujourd'hui" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.yesterday" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Gestern" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Yesterday" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Ayer" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Hier" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.daysAgoFmt" : {
|
||||
"comment" : "printf format string — %d = number of days",
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "vor %d Tagen" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "%d days ago" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "hace %d días" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "il y a %d jours" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.dayStreakFmt" : {
|
||||
"comment" : "printf format string — %d = streak count",
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "%d Tage in Folge" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "%d day streak" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "%d días seguidos" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "%d jours de suite" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.openApp" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "TabataGo öffnen →" } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Open TabataGo →" } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Abrir TabataGo →" } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Ouvrir TabataGo →" } }
|
||||
}
|
||||
},
|
||||
|
||||
"watch.complication.description" : {
|
||||
"localizations" : {
|
||||
"de" : { "stringUnit" : { "state" : "translated", "value" : "Dein aktueller Workout-Streak." } },
|
||||
"en" : { "stringUnit" : { "state" : "translated", "value" : "Your current workout streak." } },
|
||||
"es" : { "stringUnit" : { "state" : "translated", "value" : "Tu racha de entrenamiento actual." } },
|
||||
"fr" : { "stringUnit" : { "state" : "translated", "value" : "Votre série d'entraînements actuelle." } }
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
"version" : "1.0"
|
||||
}
|
||||
Reference in New Issue
Block a user