feat(app): add debug layout direction toggle (#40393)

This commit is contained in:
Luke Parker 2026-08-04 18:52:37 +10:00 committed by GitHub
parent 8721a2710b
commit c387fe190b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 281 additions and 18 deletions

View file

@ -234,7 +234,9 @@ function ResolvedDraftRoute(props: { draft: DraftTab }) {
function UiI18nBridge(props: ParentProps) {
const language = useLanguage()
return (
<I18nProvider value={{ locale: language.intl, t: language.t, plural: language.plural }}>
<I18nProvider
value={{ locale: language.intl, layoutLocale: language.layoutLocale, t: language.t, plural: language.plural }}
>
{props.children}
</I18nProvider>
)

View file

@ -60,7 +60,7 @@ function Cell(props: {
label: string
tip: string
value: string
wide?: boolean
span?: 2 | 3
}) {
const content = () => (
<div
@ -69,7 +69,8 @@ function Cell(props: {
"min-h-[20px] w-fit justify-start px-1.5 py-0.5 text-left": !!props.inline,
"justify-center text-center": !props.inline,
"min-h-[42px] w-full flex-col rounded-[8px] px-0.5 py-1": !props.inline,
"col-span-2": !!props.wide && !props.inline,
"col-span-2": props.span === 2 && !props.inline,
"col-span-3": props.span === 3 && !props.inline,
}}
>
<div
@ -116,11 +117,18 @@ function Cell(props: {
)
}
function FocusCell(props: { active: boolean; inline?: boolean; onClick: () => void }) {
function ToggleCell(props: {
active: boolean
inline?: boolean
label: string
onClick: () => void
tip: string
value: string
}) {
const content = () => (
<button
type="button"
aria-label="Force focus styles on all interactive elements"
aria-label={`${props.label}: ${props.value}`}
aria-pressed={props.active}
classList={{
"flex min-w-0 items-center font-mono uppercase hover:bg-surface-raised-base focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-border-focus": true,
@ -137,26 +145,22 @@ function FocusCell(props: { active: boolean; inline?: boolean; onClick: () => vo
"flex-col items-center": !props.inline,
}}
>
<span class="text-[10px] leading-none font-black tracking-[0.04em] opacity-70">FOCUS</span>
<span
classList={{ "leading-none font-bold": true, "text-[11px]": !!props.inline, "text-[13px]": !props.inline }}
>
{props.active ? "ON" : "OFF"}
</span>
<span class="text-[10px] leading-none font-black tracking-[0.04em] opacity-70">{props.label}</span>
<span class="text-[11px] leading-none font-bold">{props.value}</span>
</span>
</button>
)
if (props.inline) {
return (
<TooltipV2 value="Force focus styles on all interactive elements" placement="top">
<TooltipV2 value={props.tip} placement="top">
{content()}
</TooltipV2>
)
}
return (
<Tooltip value="Force focus styles on all interactive elements" placement="top">
<Tooltip value={props.tip} placement="top">
{content()}
</Tooltip>
)
@ -475,7 +479,7 @@ export function DebugBar(props: { inline?: boolean } = {}) {
"gap-[9px]": !!props.inline,
"gap-px": !props.inline,
"flex w-full flex-nowrap items-center justify-start": !!props.inline,
"grid-cols-5": !props.inline,
"grid-cols-4": !props.inline,
grid: !props.inline,
}}
>
@ -557,10 +561,25 @@ export function DebugBar(props: { inline?: boolean } = {}) {
bad={bad(heap(), 0.8)}
dim={state.heap.used === undefined}
inline={props.inline}
wide={!platform.setForceFocus}
span={platform.setForceFocus ? 2 : 3}
/>
<ToggleCell
active={language.direction() === "rtl"}
inline={props.inline}
label={language.t("debugBar.direction.label")}
tip={language.t("debugBar.direction.tip")}
value={language.t(`debugBar.direction.${language.direction()}`)}
onClick={() => language.setDirection(language.direction() === "rtl" ? "ltr" : "rtl")}
/>
{platform.setForceFocus && (
<FocusCell active={state.focus} inline={props.inline} onClick={() => void toggleFocus()} />
<ToggleCell
active={state.focus}
inline={props.inline}
label={language.t("debugBar.focus.label")}
tip={language.t("debugBar.focus.tip")}
value={language.t(state.focus ? "debugBar.focus.on" : "debugBar.focus.off")}
onClick={() => void toggleFocus()}
/>
)}
</div>
</aside>

View file

@ -15,9 +15,14 @@ import {
} from "@/i18n/desktop-native"
export type Locale = DesktopNativeLocale
export type Direction = "ltr" | "rtl"
const RTL_LOCALES: ReadonlySet<Locale> = new Set(["ar", "ur", "pa"])
function localeDirection(locale: Locale): Direction {
return RTL_LOCALES.has(locale) ? "rtl" : "ltr"
}
type RawDictionary = typeof en & typeof uiEn
type Dictionary = i18n.Flatten<RawDictionary>
type PluralKey =
@ -242,6 +247,13 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
const locale = createMemo<Locale>(() => normalizeLocale(store.locale))
const intl = createMemo(() => INTL[locale()])
const [layout, setLayout] = createStore({ direction: undefined as Direction | undefined })
const direction = createMemo(() => layout.direction ?? localeDirection(locale()))
const layoutLocale = createMemo(() => {
if (!layout.direction) return intl()
// Kobalte derives menu direction from locale rather than accepting a direction override.
return layout.direction === "rtl" ? "ar" : "en"
})
const [dict] = createResource(locale, loadDict, {
initialValue: dicts.get(initial) ?? base,
@ -270,7 +282,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
if (typeof document !== "object") return
const value = locale()
document.documentElement.lang = value
document.documentElement.dir = RTL_LOCALES.has(value) ? "rtl" : "ltr"
document.documentElement.dir = direction()
document.cookie = cookie(value)
})
@ -287,6 +299,8 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
ready,
locale,
intl,
direction,
layoutLocale,
locales: LOCALES,
label,
t,
@ -294,6 +308,9 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
setLocale(next: Locale) {
setStore("locale", normalizeLocale(next))
},
setDirection(next: Direction) {
setLayout("direction", next === localeDirection(locale()) ? undefined : next)
},
}
},
})

View file

@ -1124,6 +1124,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "كومة JS المستخدمة مقابل حد الكومة. Chromium فقط.",
"debugBar.mem.tip": "كومة JS المستخدمة مقابل حد الكومة. {{used}} من {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "فرض أنماط التركيز على جميع العناصر التفاعلية",
"debugBar.focus.on": "تشغيل",
"debugBar.focus.off": "إيقاف",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "فرض اتجاه التخطيط على التطبيق بالكامل دون تغيير اللغة المحددة",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -896,6 +896,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "İstifadə olunmuş JS yığını və yığın limiti. Yalnız Chromium.",
"debugBar.mem.tip": "İstifadə olunmuş JS yığını və yığın limiti. {{used}} və {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Bütün interaktiv elementlərə fokus üslublarını məcburi tətbiq et",
"debugBar.focus.on": "AÇIQ",
"debugBar.focus.off": "QAPALI",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Seçilmiş dili dəyişmədən bütün tətbiq üçün tərtibat istiqamətini məcburi təyin et",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "Masaüstü",
"settings.section.server": "Server",

View file

@ -1134,6 +1134,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Heap JS usado vs limite de heap. Apenas Chromium.",
"debugBar.mem.tip": "Heap JS usado vs limite de heap. {{used}} de {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Forçar estilos de foco em todos os elementos interativos",
"debugBar.focus.on": "LIGADO",
"debugBar.focus.off": "DESLIGADO",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Forçar a direção do layout de todo o aplicativo sem alterar o idioma selecionado",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -1210,6 +1210,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Korišteni JS heap naspram limita heapa. Samo Chromium.",
"debugBar.mem.tip": "Korišteni JS heap naspram limita heapa. {{used}} od {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Prisilno primijeni stilove fokusa na sve interaktivne elemente",
"debugBar.focus.on": "UKLJUČENO",
"debugBar.focus.off": "ISKLJUČENO",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Prisilno postavi smjer rasporeda cijele aplikacije bez promjene odabranog jezika",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -1084,6 +1084,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Brugt JS-heap sammenholdt med heapgrænsen. Kun Chromium.",
"debugBar.mem.tip": "Brugt JS-heap sammenholdt med heapgrænsen. {{used}} af {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Gennemtving fokusstile for alle interaktive elementer",
"debugBar.focus.on": "TIL",
"debugBar.focus.off": "FRA",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Gennemtving layoutretningen for hele appen uden at ændre det valgte sprog",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -1029,6 +1029,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Belegter JS-Heap im Verhältnis zum Heap-Limit. Nur Chromium.",
"debugBar.mem.tip": "Belegter JS-Heap im Verhältnis zum Heap-Limit. {{used}} von {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Fokusstile für alle interaktiven Elemente erzwingen",
"debugBar.focus.on": "EIN",
"debugBar.focus.off": "AUS",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Layoutrichtung für die gesamte App erzwingen, ohne die ausgewählte Sprache zu ändern",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Strg",
"common.key.alt": "Alt",
"common.key.shift": "Umschalt",

View file

@ -868,6 +868,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Used JS heap vs heap limit. Chromium only.",
"debugBar.mem.tip": "Used JS heap vs heap limit. {{used}} of {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Force focus styles on all interactive elements",
"debugBar.focus.on": "ON",
"debugBar.focus.off": "OFF",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Force the full app layout direction without changing the selected language",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",

View file

@ -1218,6 +1218,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Heap JS usado vs límite de heap. Solo Chromium.",
"debugBar.mem.tip": "Heap JS usado vs límite de heap. {{used}} de {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Forzar los estilos de foco en todos los elementos interactivos",
"debugBar.focus.on": "SÍ",
"debugBar.focus.off": "NO",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Forzar la dirección del diseño de toda la aplicación sin cambiar el idioma seleccionado",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Mayús",

View file

@ -786,6 +786,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Käytetty JS-keko suhteessa keon rajaan. Vain Chromium.",
"debugBar.mem.tip": "Käytetty JS-keko suhteessa keon rajaan. {{used}} / {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Pakota kohdistustyylit kaikkiin vuorovaikutteisiin elementteihin",
"debugBar.focus.on": "KÄYTÖSSÄ",
"debugBar.focus.off": "EI KÄYTÖSSÄ",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Pakota koko sovelluksen asettelun suunta valittua kieltä muuttamatta",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "Työpöytä",
"settings.section.server": "Palvelin",

View file

@ -1145,6 +1145,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Tas JS utilisé vs limite de tas. Chromium uniquement.",
"debugBar.mem.tip": "Tas JS utilisé vs limite de tas. {{used}} sur {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Forcer les styles de focus sur tous les éléments interactifs",
"debugBar.focus.on": "ACTIVÉ",
"debugBar.focus.off": "DÉSACTIVÉ",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Forcer le sens de disposition de toute lapplication sans changer la langue sélectionnée",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Maj",

View file

@ -895,6 +895,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "उपयोग किया गया JS हीप बनाम हीप सीमा। केवल Chromium।",
"debugBar.mem.tip": "उपयोग किया गया JS हीप बनाम हीप सीमा। {{limit}} में से {{used}}।",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "सभी इंटरैक्टिव एलिमेंट पर फ़ोकस स्टाइल ज़बरदस्ती लागू करें",
"debugBar.focus.on": "चालू",
"debugBar.focus.off": "बंद",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "चुनी गई भाषा बदले बिना पूरे ऐप की लेआउट दिशा ज़बरदस्ती सेट करें",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "डेस्कटॉप",
"settings.section.server": "सर्वर",

View file

@ -963,6 +963,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Heap JS terpakai vs batas heap. Khusus Chromium.",
"debugBar.mem.tip": "Heap JS terpakai vs batas heap. {{used}} dari {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Paksa gaya fokus pada semua elemen interaktif",
"debugBar.focus.on": "AKTIF",
"debugBar.focus.off": "NONAKTIF",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Paksa arah tata letak seluruh aplikasi tanpa mengubah bahasa yang dipilih",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",

View file

@ -807,6 +807,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Heap JS utilizzato rispetto al limite dell'heap. Solo Chromium.",
"debugBar.mem.tip": "Heap JS utilizzato rispetto al limite dell'heap. {{used}} di {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Forza gli stili di focus su tutti gli elementi interattivi",
"debugBar.focus.on": "ON",
"debugBar.focus.off": "OFF",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Forza la direzione del layout dellintera app senza cambiare la lingua selezionata",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "Desktop",
"settings.section.server": "Server",

View file

@ -1116,6 +1116,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "使用中の JS ヒープ対ヒープ制限。Chromium のみ。",
"debugBar.mem.tip": "使用中の JS ヒープ対ヒープ制限。{{limit}} 中 {{used}}。",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "すべてのインタラクティブ要素にフォーカススタイルを強制適用",
"debugBar.focus.on": "オン",
"debugBar.focus.off": "オフ",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "選択中の言語を変更せずに、アプリ全体のレイアウト方向を強制設定",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -840,6 +840,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "사용된 JS 힙 대 힙 제한. Chromium 전용.",
"debugBar.mem.tip": "사용된 JS 힙 대 힙 제한. {{limit}} 중 {{used}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "모든 대화형 요소에 포커스 스타일 강제 적용",
"debugBar.focus.on": "켬",
"debugBar.focus.off": "끔",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "선택한 언어를 변경하지 않고 전체 앱의 레이아웃 방향 강제 설정",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -896,6 +896,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Gebruikte JS-heap versus heap-limiet. Alleen Chromium.",
"debugBar.mem.tip": "Gebruikte JS-heap versus heaplimiet. {{used}} van {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Dwing focusstijlen af voor alle interactieve elementen",
"debugBar.focus.on": "AAN",
"debugBar.focus.off": "UIT",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Dwing de lay-outrichting voor de hele app af zonder de geselecteerde taal te wijzigen",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "Desktop",
"settings.section.server": "Server",

View file

@ -1037,6 +1037,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Brukt JS-heap kontra heap-grense. Kun Chromium.",
"debugBar.mem.tip": "Brukt JS-heap kontra heap-grense. {{used}} av {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Tving fokusstiler på alle interaktive elementer",
"debugBar.focus.on": "PÅ",
"debugBar.focus.off": "AV",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Tving layoutretningen for hele appen uten å endre valgt språk",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -893,6 +893,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "جے ایس ہیپ بمقابلہ ہیپ لیمٹ استعمال کیتا گیا۔ صرف Chromium۔",
"debugBar.mem.tip": "ورتیا JS ہیپ تے ہیپ دی حد۔ {{limit}} وچوں {{used}}۔",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "سارے انٹرایکٹو عناصر اُتے فوکس سٹائل لازمی لاگو کرو",
"debugBar.focus.on": "چالو",
"debugBar.focus.off": "بند",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "چُنی ہوئی زبان نوں بدلے بغیر پوری ایپ دے لے آؤٹ دی سمت لازمی مقرر کرو",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode ڈیسک ٹاپ",
"settings.section.desktop": "ڈیسک ٹاپ",
"settings.section.server": "سرور",

View file

@ -1137,6 +1137,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Wykorzystana pamięć sterty JS względem jej limitu. Tylko Chromium.",
"debugBar.mem.tip": "Wykorzystana pamięć sterty JS względem jej limitu: {{used}} z {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Wymuś style fokusu dla wszystkich elementów interaktywnych",
"debugBar.focus.on": "WŁ.",
"debugBar.focus.off": "WYŁ.",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Wymuś kierunek układu całej aplikacji bez zmiany wybranego języka",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -1215,6 +1215,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Используемая куча JS по сравнению с лимитом кучи. Только Chromium.",
"debugBar.mem.tip": "Используемая куча JS по сравнению с лимитом кучи. {{used}} из {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Принудительно применить стили фокуса ко всем интерактивным элементам",
"debugBar.focus.on": "ВКЛ.",
"debugBar.focus.off": "ВЫКЛ.",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Принудительно задать направление макета всего приложения, не меняя выбранный язык",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -892,6 +892,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Använd JS-heap jämfört med heapgränsen. Endast Chromium.",
"debugBar.mem.tip": "Använd JS-heap jämfört med heapgränsen. {{used}} av {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Tvinga fram fokusstilar på alla interaktiva element",
"debugBar.focus.on": "PÅ",
"debugBar.focus.off": "AV",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Tvinga fram hela appens layoutriktning utan att ändra valt språk",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "Skrivbord",
"settings.section.server": "Server",

View file

@ -1191,6 +1191,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "JS heap ที่ใช้เทียบกับขีดจำกัด heap เฉพาะ Chromium",
"debugBar.mem.tip": "JS heap ที่ใช้เทียบกับขีดจำกัด heap {{used}} จาก {{limit}}",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "บังคับใช้สไตล์โฟกัสกับองค์ประกอบแบบโต้ตอบทั้งหมด",
"debugBar.focus.on": "เปิด",
"debugBar.focus.off": "ปิด",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "บังคับกำหนดทิศทางเค้าโครงของทั้งแอปโดยไม่เปลี่ยนภาษาที่เลือก",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -1213,6 +1213,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Kullanılan JS yığınının yığın sınırına oranı. Yalnızca Chromium.",
"debugBar.mem.tip": "Kullanılan JS yığınının yığın sınırına oranı: {{used}} / {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Tüm etkileşimli öğelere odak stillerini zorla uygula",
"debugBar.focus.on": "AÇIK",
"debugBar.focus.off": "KAPALI",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Seçili dili değiştirmeden tüm uygulamanın düzen yönünü zorla ayarla",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -977,6 +977,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Використана купа JS проти ліміту купи. Тільки Chromium.",
"debugBar.mem.tip": "Використана купа JS проти ліміту купи. {{used}} з {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Примусово застосувати стилі фокуса до всіх інтерактивних елементів",
"debugBar.focus.on": "УВІМК.",
"debugBar.focus.off": "ВИМК.",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Примусово задати напрямок макета всієї програми, не змінюючи вибрану мову",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",

View file

@ -896,6 +896,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "استعمال شدہ JS ہیپ بمقابلہ ہیپ کی حد۔ صرف Chromium۔",
"debugBar.mem.tip": "استعمال شدہ JS ہیپ بمقابلہ ہیپ کی حد۔ {{limit}} میں سے {{used}}۔",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "تمام تفاعلی عناصر پر فوکس اسٹائلز لازماً لاگو کریں",
"debugBar.focus.on": "چالو",
"debugBar.focus.off": "بند",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "منتخب زبان تبدیل کیے بغیر پوری ایپ کے لے آؤٹ کی سمت لازماً مقرر کریں",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode ڈیسک ٹاپ",
"settings.section.desktop": "ڈیسک ٹاپ",
"settings.section.server": "سرور",

View file

@ -898,6 +898,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "Bộ nhớ heap JS đã dùng so với giới hạn heap. Chỉ hỗ trợ Chromium.",
"debugBar.mem.tip": "Đã sử dụng JS heap so với giới hạn heap. {{used}} của {{limit}}.",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "Buộc áp dụng kiểu tiêu điểm cho mọi phần tử tương tác",
"debugBar.focus.on": "BẬT",
"debugBar.focus.off": "TẮT",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "Buộc đặt hướng bố cục cho toàn bộ ứng dụng mà không thay đổi ngôn ngữ đã chọn",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"app.name.desktop": "OpenCode Desktop",
"settings.section.desktop": "Desktop",
"settings.section.server": "Máy chủ",

View file

@ -1180,6 +1180,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "使用的 JS 堆与堆限制。仅限 Chromium。",
"debugBar.mem.tip": "使用的 JS 堆与堆限制。{{used}} / {{limit}}。",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "强制所有交互元素显示焦点样式",
"debugBar.focus.on": "开",
"debugBar.focus.off": "关",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "在不更改所选语言的情况下,强制设置整个应用的布局方向",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -1176,6 +1176,14 @@ export const dict = {
"debugBar.mem.label": "MEM",
"debugBar.mem.tipUnavailable": "使用的 JS 堆積與堆積限制。僅限 Chromium。",
"debugBar.mem.tip": "使用的 JS 堆積與堆積限制。{{used}} / {{limit}}。",
"debugBar.focus.label": "FOCUS",
"debugBar.focus.tip": "強制所有互動元素顯示焦點樣式",
"debugBar.focus.on": "開啟",
"debugBar.focus.off": "關閉",
"debugBar.direction.label": "DIR",
"debugBar.direction.tip": "在不變更所選語言的情況下,強制設定整個應用程式的版面配置方向",
"debugBar.direction.ltr": "LTR",
"debugBar.direction.rtl": "RTL",
"common.key.ctrl": "Ctrl",
"common.key.alt": "Alt",
"common.key.shift": "Shift",

View file

@ -18,6 +18,7 @@ export type UiI18nParams = Record<string, string | number | boolean>
export type UiI18n = {
locale: Accessor<string>
layoutLocale?: Accessor<string>
t: (key: UiI18nKey, params?: UiI18nParams) => string
plural: (key: UiI18nPluralKey, count: number, params?: UiI18nParams) => string
}
@ -60,7 +61,7 @@ const Context = createContext<UiI18n>(fallback)
function UiI18nProvider(props: ParentProps<{ value: UiI18n }>) {
return (
<I18nProvider locale={props.value.locale()}>
<I18nProvider locale={(props.value.layoutLocale ?? props.value.locale)()}>
<Context.Provider value={props.value}>{props.children}</Context.Provider>
</I18nProvider>
)