diff --git a/src/timelines/ChooseTootLang.tsx b/src/timelines/ChooseTootLang.tsx new file mode 100644 index 0000000..8405bb1 --- /dev/null +++ b/src/timelines/ChooseTootLang.tsx @@ -0,0 +1,86 @@ +import { + For, + onMount, + type Component, + type JSX, +} from "solid-js"; +import Scaffold from "../material/Scaffold"; +import { + AppBar, + IconButton, + List, + ListItemButton, + ListItemSecondaryAction, + ListItemText, + Radio, + Toolbar, +} from "@suid/material"; +import { Close as CloseIcon } from "@suid/icons-material"; +import iso639_1 from "iso-639-1"; +import { createTranslator } from "../platform/i18n"; +import { Title } from "../material/typography"; + +type ChooseTootLangProps = { + code: string; + onCodeChange: (ncode?: string) => void; + onClose?: JSX.EventHandlerUnion; +}; + +const ChooseTootLang: Component = (props) => { + let listRef: HTMLUListElement; + const [t] = createTranslator( + (code) => + import(`./i18n/${code}.json`) as Promise<{ + default: Record; + }>, + ); + + onMount(() => { + const code = props.code; + const el = listRef.querySelector(`[data-langcode="${code}"]`); + if (el) { + el.scrollIntoView({ behavior: "auto" }); + } + }); + + return ( + + + + + + {t("Choose Language")} + + + } + > + + + {(code) => ( + props.onCodeChange(code)} + > + {iso639_1.getNativeName(code)} + + + + + )} + + + + ); +}; + +export default ChooseTootLang; diff --git a/src/timelines/ReplyEditor.tsx b/src/timelines/ReplyEditor.tsx index 0f146c4..51259b9 100644 --- a/src/timelines/ReplyEditor.tsx +++ b/src/timelines/ReplyEditor.tsx @@ -27,11 +27,16 @@ import { People as PeopleIcon, ThreeP as ThreePIcon, ListAlt as ListAltIcon, + Visibility, + Translate, } from "@suid/icons-material"; import type { Account } from "../accounts/stores"; import tootComposers from "./TootComposer.module.css"; import { makeEventListener } from "@solid-primitives/event-listener"; import BottomSheet from "../material/BottomSheet"; +import { useLanguage } from "../platform/i18n"; +import iso639_1 from "iso-639-1"; +import ChooseTootLang from "./ChooseTootLang"; type TootVisibility = "public" | "unlisted" | "private" | "direct"; @@ -154,17 +159,19 @@ const TootVisibilityPickerDialog: Component<{ const ReplyEditor: Component<{ profile: Account; replyToDisplayName: string; - isTyping?: boolean - onTypingChange: (value: boolean) => void + isTyping?: boolean; + onTypingChange: (value: boolean) => void; }> = (props) => { let inputRef: HTMLTextAreaElement; const buttonId = createUniqueId(); const menuId = createUniqueId(); - const typing = () => props.isTyping - const setTyping = (v: boolean) => props.onTypingChange(v) + const typing = () => props.isTyping; + const setTyping = (v: boolean) => props.onTypingChange(v); const [visibility, setVisibility] = createSignal("public"); const [permPicker, setPermPicker] = createSignal(false); + const [language, setLanguage] = createSignal(useLanguage()().split("-")[0]); + const [langPickerOpen, setLangPickerOpen] = createSignal(false); onMount(() => { makeEventListener(inputRef, "focus", () => setTyping(true)); @@ -218,7 +225,13 @@ const ReplyEditor: Component<{ "margin-top": "8px", }} > + @@ -230,6 +243,17 @@ const ReplyEditor: Component<{ visibility={visibility()} onVisibilityChange={setVisibility} /> + + setLangPickerOpen(false)} + > + + ); }; diff --git a/src/timelines/i18n/en.json b/src/timelines/i18n/en.json new file mode 100644 index 0000000..f9bed6a --- /dev/null +++ b/src/timelines/i18n/en.json @@ -0,0 +1,3 @@ +{ + "Choose Language": "Choose Language" +} \ No newline at end of file diff --git a/src/timelines/i18n/zh-Hans.json b/src/timelines/i18n/zh-Hans.json new file mode 100644 index 0000000..06d6bfb --- /dev/null +++ b/src/timelines/i18n/zh-Hans.json @@ -0,0 +1,3 @@ +{ + "Choose Language": "选择语言" +} \ No newline at end of file