feat(i18n): extract remaining screens into en/zh-Hans catalogs; full Simplified Chinese coverage (closes #68) (#103)
Extends the i18n infra from #97 (Settings screen only) to the rest of the app: session chat screen, connection add/edit/list screens, sessions list (incl. directory grouping from #96), navigation titles, notifications category metadata, error boundary, telemetry consent modal, auth gate, and every chat UI component (permission/question prompts, status indicator, model/variant pickers, directory switcher/browser, reasoning block, tool call card, session info). - 244 new keys added to en.json/zh-Hans.json with reviewed, natural Simplified Chinese (not machine-garbage), keeping key sets identical. - User content, server URLs, code snippets, log/error-detail text, and diagnostics-classify.ts (pure dependency-free module feeding Sentry/ support reports) are intentionally left untranslated per scope. - Interpolation used for counts/names (e.g. reconnect attempt, files count, connection name in delete confirmations); categoryMeta/ CONNECTION_TYPES switched to labelKey indirection since they're module-level constants evaluated before i18next is guaranteed ready. - Added src/lib/i18n/catalog-parity.test.ts (node --test) asserting en.json/zh-Hans.json expose identical key sets and no empty values, to catch future locale drift. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useState } from "react"
|
||||
import { View, Text, TextInput, TouchableOpacity, StyleSheet } from "react-native"
|
||||
import { Ionicons } from "@expo/vector-icons"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
interface QuestionOption {
|
||||
label: string
|
||||
@@ -26,6 +27,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export function QuestionPrompt({ request, isDark, onReply, onReject }: Props) {
|
||||
const { t } = useTranslation()
|
||||
const [answers, setAnswers] = useState<string[][]>(request.questions.map(() => []))
|
||||
const [custom, setCustom] = useState("")
|
||||
const [showCustom, setShowCustom] = useState(false)
|
||||
@@ -66,7 +68,7 @@ export function QuestionPrompt({ request, isDark, onReply, onReject }: Props) {
|
||||
<View style={[s.card, isDark && s.cardDark]}>
|
||||
<View style={s.header}>
|
||||
<Ionicons name="chatbubble-ellipses-outline" size={18} color="#8b5cf6" />
|
||||
<Text style={[s.title, isDark && s.textWhite]}>{q.header || "Question"}</Text>
|
||||
<Text style={[s.title, isDark && s.textWhite]}>{q.header || t("chat.questionPrompt.headerFallback")}</Text>
|
||||
</View>
|
||||
<Text style={[s.question, isDark && s.textWhite]}>{q.question}</Text>
|
||||
|
||||
@@ -95,7 +97,7 @@ export function QuestionPrompt({ request, isDark, onReply, onReject }: Props) {
|
||||
<View style={s.customRow}>
|
||||
<TextInput
|
||||
style={[s.customInput, isDark && s.customInputDark]}
|
||||
placeholder="Type your answer..."
|
||||
placeholder={t("chat.questionPrompt.answerPlaceholder")}
|
||||
placeholderTextColor={isDark ? "#666666" : "#999999"}
|
||||
value={custom}
|
||||
onChangeText={setCustom}
|
||||
@@ -108,14 +110,14 @@ export function QuestionPrompt({ request, isDark, onReply, onReject }: Props) {
|
||||
</View>
|
||||
) : (
|
||||
<TouchableOpacity style={[s.option, isDark && s.optionDark]} onPress={() => setShowCustom(true)}>
|
||||
<Text style={[s.optionLabel, { color: "#8b5cf6" }]}>Type your own answer</Text>
|
||||
<Text style={[s.optionLabel, { color: "#8b5cf6" }]}>{t("chat.questionPrompt.customAnswerLabel")}</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</View>
|
||||
|
||||
<View style={s.footer}>
|
||||
<TouchableOpacity onPress={onReject}>
|
||||
<Text style={[s.dismiss, isDark && s.metaDark]}>Dismiss</Text>
|
||||
<Text style={[s.dismiss, isDark && s.metaDark]}>{t("chat.questionPrompt.dismiss")}</Text>
|
||||
</TouchableOpacity>
|
||||
{(request.questions.length > 1 || q.multiple) && (
|
||||
<TouchableOpacity
|
||||
@@ -128,7 +130,9 @@ export function QuestionPrompt({ request, isDark, onReply, onReject }: Props) {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Text style={s.submitText}>{current < request.questions.length - 1 ? "Next" : "Submit"}</Text>
|
||||
<Text style={s.submitText}>
|
||||
{current < request.questions.length - 1 ? t("chat.questionPrompt.next") : t("chat.questionPrompt.submit")}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user