feat(i18n): add internationalization with i18next and expo-localization

This commit is contained in:
2026-08-08 10:09:30 +02:00
parent 408a2fa10c
commit 9946e78858
81 changed files with 1820 additions and 125 deletions
@@ -0,0 +1,48 @@
import { View, Text, Pressable } from "react-native";
import { useTranslation } from "react-i18next";
import { useSettings } from "../../../providers/WatchProvider";
import { LANGUAGES } from "@i18n/index";
export function LanguagePicker() {
const { t } = useTranslation("settings");
const { language, setLanguage } = useSettings();
return (
<View className="mb-6">
<Text className="text-sm font-medium text-slate-500 mb-2">{t("language")}</Text>
<View className="flex-row flex-wrap gap-2">
<Pressable
onPress={() => setLanguage("system")}
className={`px-3 py-2 rounded-xl ${
language === "system" ? "bg-sky-500" : "bg-slate-100"
}`}
>
<Text
className={`text-sm font-medium ${
language === "system" ? "text-white" : "text-slate-600"
}`}
>
{t("systemLanguage")}
</Text>
</Pressable>
{LANGUAGES.map((lang) => (
<Pressable
key={lang.code}
onPress={() => setLanguage(lang.code)}
className={`px-3 py-2 rounded-xl ${
language === lang.code ? "bg-sky-500" : "bg-slate-100"
}`}
>
<Text
className={`text-sm font-medium ${
language === lang.code ? "text-white" : "text-slate-600"
}`}
>
{lang.label}
</Text>
</Pressable>
))}
</View>
</View>
);
}
@@ -1,15 +1,20 @@
import { View, Text, Pressable } from "react-native";
import { useTranslation } from "react-i18next";
import { useSettings } from "../../../providers/WatchProvider";
import { LanguagePicker } from "../components/LanguagePicker";
export function SettingsScreen() {
const { t } = useTranslation("settings");
const { poolLength, setPoolLength } = useSettings();
return (
<View className="flex-1 bg-white p-4">
<Text className="text-2xl font-bold text-slate-900 mb-6">Settings</Text>
<Text className="text-2xl font-bold text-slate-900 mb-6">{t("settings")}</Text>
<LanguagePicker />
<View className="mb-6">
<Text className="text-sm font-medium text-slate-500 mb-2">Default Pool Length</Text>
<Text className="text-sm font-medium text-slate-500 mb-2">{t("defaultPoolLength")}</Text>
<View className="flex-row gap-3">
{[25, 50].map((len) => (
<Pressable
@@ -32,7 +37,7 @@ export function SettingsScreen() {
</View>
<View className="border-t border-slate-200 pt-4 mt-2">
<Text className="text-sm text-slate-400">SwimBuddy v1.0.0</Text>
<Text className="text-sm text-slate-400">{t("version")}</Text>
</View>
</View>
);