Internationalize Bible UI and add locale-aware translation fetch
This commit is contained in:
@@ -4,7 +4,8 @@ import { ActivityIndicator, Button, Chip, Divider, Text, TextInput } from "react
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import { useSnapshot } from "valtio";
|
||||
import GlobalState from "../contexts/GlobalState.js";
|
||||
import { BIBLE_BOOKS, createBibleToken, fetchBiblePassage, getBookChapterCount } from "../utils/bibleReferences.js";
|
||||
import { BIBLE_BOOKS, createBibleToken, fetchBibleChapter, fetchBiblePassage, getBookChapterCount } from "../utils/bibleReferences.js";
|
||||
import i18n from "../i18nMessages.js";
|
||||
|
||||
const BiblePicker = ({ route }) => {
|
||||
const navigation = useNavigation();
|
||||
@@ -57,11 +58,11 @@ const BiblePicker = ({ route }) => {
|
||||
setError("");
|
||||
setLoadingPreview(true);
|
||||
try {
|
||||
const passage = await fetchBiblePassage(reference);
|
||||
const passage = await fetchBiblePassage(reference, i18n.locale);
|
||||
setPreview(passage);
|
||||
} catch (_err) {
|
||||
setPreview(null);
|
||||
setError("Unable to load this Bible passage.");
|
||||
setError(i18n.t("message.unableLoadPassage"));
|
||||
} finally {
|
||||
setLoadingPreview(false);
|
||||
}
|
||||
@@ -74,9 +75,7 @@ const BiblePicker = ({ route }) => {
|
||||
}
|
||||
setLoadingVerses(true);
|
||||
try {
|
||||
const response = await fetch(`https://bible-api.com/${encodeURIComponent(`${book} ${chapterNumber}`)}`);
|
||||
if (!response.ok) throw new Error("Failed chapter fetch");
|
||||
const payload = await response.json();
|
||||
const payload = await fetchBibleChapter(`${book} ${chapterNumber}`, i18n.locale);
|
||||
const options = Array.isArray(payload?.verses)
|
||||
? payload.verses.map((v) => String(v?.verse || "")).filter(Boolean)
|
||||
: [];
|
||||
@@ -103,9 +102,9 @@ const BiblePicker = ({ route }) => {
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, paddingHorizontal: 12, paddingTop: 12 }}>
|
||||
<Text style={{ fontSize: 22, fontWeight: "700", marginBottom: 6 }}>Bible Reference</Text>
|
||||
<Text style={{ fontSize: 22, fontWeight: "700", marginBottom: 6 }}>{i18n.t("message.bibleReferenceTitle")}</Text>
|
||||
<Text style={{ color: "#6b7280", marginBottom: 10 }}>
|
||||
Pick a reference to insert into your {target === "chat" ? "chat message" : "post"}.
|
||||
{target === "chat" ? i18n.t("message.biblePickerSubtitleChat") : i18n.t("message.biblePickerSubtitlePost")}
|
||||
</Text>
|
||||
|
||||
<TextInput
|
||||
@@ -117,14 +116,14 @@ const BiblePicker = ({ route }) => {
|
||||
/>
|
||||
<View style={{ flexDirection: "row", marginTop: 8, justifyContent: "space-between" }}>
|
||||
<Button mode="outlined" onPress={() => loadPreviewForReference(computedReference)} loading={loadingPreview}>
|
||||
Preview
|
||||
{i18n.t("message.preview")}
|
||||
</Button>
|
||||
<Button mode="contained" disabled={!computedReference} onPress={() => addReferenceToCaller(computedReference)}>
|
||||
Use Reference
|
||||
{i18n.t("message.useReference")}
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
{computedReference ? <Text style={{ marginTop: 8, color: "#374151" }}>Selected: {computedReference}</Text> : null}
|
||||
{computedReference ? <Text style={{ marginTop: 8, color: "#374151" }}>{i18n.t("message.selected")}: {computedReference}</Text> : null}
|
||||
{preview?.text ? (
|
||||
<Pressable
|
||||
onPress={() => navigation.navigate("BibleChapter", { reference: computedReference, selectable: true })}
|
||||
@@ -134,7 +133,7 @@ const BiblePicker = ({ route }) => {
|
||||
<Text style={{ marginTop: 4, color: "#4b5563", fontSize: 12 }}>
|
||||
{preview.reference} ({preview.translation})
|
||||
</Text>
|
||||
<Text style={{ marginTop: 4, color: "#6b7280", fontSize: 12 }}>Tap preview to pick verse from chapter</Text>
|
||||
<Text style={{ marginTop: 4, color: "#6b7280", fontSize: 12 }}>{i18n.t("message.tapPreviewPickVerse")}</Text>
|
||||
</Pressable>
|
||||
) : null}
|
||||
{error ? <Text style={{ marginTop: 8, color: "#b91c1c" }}>{error}</Text> : null}
|
||||
@@ -143,27 +142,27 @@ const BiblePicker = ({ route }) => {
|
||||
|
||||
<View style={{ flexDirection: "row", marginBottom: 10 }}>
|
||||
<Button mode={activeStep === "book" ? "contained-tonal" : "text"} onPress={() => setActiveStep("book")}>
|
||||
Book
|
||||
{i18n.t("message.book")}
|
||||
</Button>
|
||||
<Button
|
||||
mode={activeStep === "chapter" ? "contained-tonal" : "text"}
|
||||
disabled={!selectedBook}
|
||||
onPress={() => setActiveStep("chapter")}
|
||||
>
|
||||
Chapter
|
||||
{i18n.t("message.chapter")}
|
||||
</Button>
|
||||
<Button
|
||||
mode={activeStep === "verse" ? "contained-tonal" : "text"}
|
||||
disabled={!selectedBook || !chapter}
|
||||
onPress={() => setActiveStep("verse")}
|
||||
>
|
||||
Verse
|
||||
{i18n.t("message.verse")}
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
{activeStep === "book" ? (
|
||||
<>
|
||||
<Text style={{ fontSize: 14, fontWeight: "600", marginBottom: 8 }}>Books</Text>
|
||||
<Text style={{ fontSize: 14, fontWeight: "600", marginBottom: 8 }}>{i18n.t("message.books")}</Text>
|
||||
<FlatList
|
||||
data={filteredBooks}
|
||||
numColumns={2}
|
||||
@@ -192,7 +191,7 @@ const BiblePicker = ({ route }) => {
|
||||
{activeStep === "chapter" ? (
|
||||
<>
|
||||
<Text style={{ fontSize: 14, fontWeight: "600", marginBottom: 8 }}>
|
||||
Chapters {selectedBook ? `(${selectedBook})` : ""}
|
||||
{i18n.t("message.chapters")} {selectedBook ? `(${selectedBook})` : ""}
|
||||
</Text>
|
||||
<FlatList
|
||||
data={chapterOptions}
|
||||
@@ -220,7 +219,7 @@ const BiblePicker = ({ route }) => {
|
||||
{activeStep === "verse" ? (
|
||||
<>
|
||||
<Text style={{ fontSize: 14, fontWeight: "600", marginBottom: 8 }}>
|
||||
Verses {selectedBook && chapter ? `(${selectedBook} ${chapter})` : ""}
|
||||
{i18n.t("message.verses")} {selectedBook && chapter ? `(${selectedBook} ${chapter})` : ""}
|
||||
</Text>
|
||||
{loadingVerses ? (
|
||||
<ActivityIndicator style={{ marginTop: 8 }} />
|
||||
|
||||
Reference in New Issue
Block a user