feat(i18n): localize hardcoded application copy (#40377)

Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com>
This commit is contained in:
opencode-agent[bot]
2026-08-04 16:56:03 +10:00
committed by GitHub
parent 5f29a82190
commit bf04bbffe9
121 changed files with 4758 additions and 331 deletions
+2 -2
View File
@@ -109,8 +109,8 @@
width: 20px;
height: 20px;
margin-top: -2px;
margin-right: -2px;
margin-left: auto;
margin-inline-end: -2px;
margin-inline-start: auto;
border-radius: 4px;
flex-shrink: 0;
cursor: pointer;
+3 -1
View File
@@ -1,5 +1,6 @@
import { Dialog as Kobalte } from "@kobalte/core/dialog"
import { type ComponentProps, type JSXElement, type ParentProps, Show, children, splitProps } from "solid-js"
import { useI18n } from "../../context/i18n"
import "./dialog-v2.css"
export interface DialogProps extends ParentProps {
@@ -51,6 +52,7 @@ export function DialogTitleGroup(props: DialogTitleGroupProps) {
}
export function DialogHeader(props: DialogHeaderProps) {
const i18n = useI18n()
const [local] = splitProps(props, ["closeLabel", "hideClose", "children"])
const hideClose = () => local.hideClose === true
@@ -58,7 +60,7 @@ export function DialogHeader(props: DialogHeaderProps) {
<div data-slot="dialog-header" data-hide-close={hideClose() ? "" : undefined}>
{local.children}
{!hideClose() && (
<Kobalte.CloseButton data-slot="dialog-close-button" aria-label={local.closeLabel ?? "Close"}>
<Kobalte.CloseButton data-slot="dialog-close-button" aria-label={local.closeLabel ?? i18n.t("ui.common.close")}>
<svg
width="16"
height="16"
@@ -1,5 +1,6 @@
import { type ComponentProps, type JSX, Show, splitProps } from "solid-js"
import { Icon } from "./icon"
import { useI18n } from "../../context/i18n"
import "./inline-input-v2.css"
export interface InlineInputV2Props extends Omit<ComponentProps<"input">, "type" | "prefix"> {
@@ -22,6 +23,7 @@ export interface InlineInputV2Props extends Omit<ComponentProps<"input">, "type"
}
export function InlineInputV2(props: InlineInputV2Props) {
const i18n = useI18n()
const [local, inputProps] = splitProps(props, [
"class",
"classList",
@@ -92,7 +94,7 @@ export function InlineInputV2(props: InlineInputV2Props) {
<button
type="button"
data-slot="inline-input-v2-icon-button"
aria-label={local.copyLabel ?? "Copy"}
aria-label={local.copyLabel ?? i18n.t("ui.message.copy")}
disabled={local.disabled}
onClick={local.onCopyClick}
>
@@ -228,7 +228,7 @@
border-radius: 4px;
background: transparent;
color: var(--v2-text-text-base);
text-align: left;
text-align: start;
cursor: pointer;
}
@@ -1,5 +1,6 @@
import { For, Show, createSignal, onMount, splitProps, type ComponentProps, type JSX } from "solid-js"
import { FileIcon } from "../../components/file-icon"
import { useI18n } from "../../context/i18n"
import { useFilteredList } from "../../hooks"
import { ButtonV2 } from "./button-v2"
import "./line-comment-v2.css"
@@ -86,6 +87,7 @@ function pathDirectory(path: string) {
}
export function LineCommentEditorV2(props: LineCommentEditorV2Props) {
const i18n = useI18n()
let textareaRef: HTMLTextAreaElement | undefined
const [mentionOpen, setMentionOpen] = createSignal(false)
@@ -106,7 +108,7 @@ export function LineCommentEditorV2(props: LineCommentEditorV2Props) {
"classList",
])
const heading = () => local.heading ?? "Comment"
const heading = () => local.heading ?? i18n.t("ui.lineComment.submit")
const canSubmit = () => local.value.trim().length > 0
const closeMention = () => {
@@ -211,7 +213,7 @@ export function LineCommentEditorV2(props: LineCommentEditorV2Props) {
}}
data-slot="line-comment-v2-textarea"
rows={local.rows ?? 3}
placeholder={local.placeholder ?? "Add context for this change"}
placeholder={local.placeholder ?? i18n.t("ui.lineComment.contextPlaceholder")}
value={local.value}
onInput={(e) => {
local.onInput(e.currentTarget.value)
@@ -291,10 +293,10 @@ export function LineCommentEditorV2(props: LineCommentEditorV2Props) {
<div data-slot="line-comment-v2-footer-meta">{local.selection}</div>
<div data-slot="line-comment-v2-footer-actions">
<ButtonV2 type="button" size="normal" variant="neutral" onClick={() => local.onCancel()}>
{local.cancelLabel ?? "Cancel"}
{local.cancelLabel ?? i18n.t("ui.lineComment.cancel")}
</ButtonV2>
<ButtonV2 type="button" size="normal" variant="contrast" disabled={!canSubmit()} onClick={submit}>
{local.submitLabel ?? "Comment"}
{local.submitLabel ?? i18n.t("ui.lineComment.submit")}
</ButtonV2>
</div>
</div>
+4 -4
View File
@@ -71,7 +71,7 @@
[data-component="tabs-v2"] [data-slot="tabs-v2-close-button"] {
width: 20px;
height: 20px;
margin-left: -5px;
margin-inline-start: -5px;
flex: none;
display: flex;
align-items: center;
@@ -109,7 +109,7 @@
background-color: var(--v2-border-border-base);
position: absolute;
bottom: 0px;
left: -8px;
inset-inline-start: -8px;
}
[data-component="tabs-v2"][data-variant="pill"][data-orientation="horizontal"] [data-slot="tabs-v2-list"] {
@@ -183,12 +183,12 @@
padding: 12px;
gap: 4px;
overflow-y: auto;
border-right: 1px solid var(--v2-border-border-base);
border-inline-end: 1px solid var(--v2-border-border-base);
}
[data-component="tabs-v2"][data-variant="settings"][data-orientation="vertical"] [data-slot="tabs-v2-section-title"] {
width: 100%;
padding-left: 4px;
padding-inline-start: 4px;
color: var(--v2-text-text-muted);
font-size: 12px;
font-weight: 500;
+4 -2
View File
@@ -1,6 +1,7 @@
import { Tabs as Kobalte } from "@kobalte/core/tabs"
import { Show, splitProps, type JSX } from "solid-js"
import type { ComponentProps, ParentProps, Component } from "solid-js"
import { useI18n } from "../../context/i18n"
import "./tabs-v2.css"
export interface TabsV2Props extends ComponentProps<typeof Kobalte> {
@@ -74,7 +75,7 @@ function TabsV2Trigger(props: ParentProps<TabsV2TriggerProps>) {
{split.children}
<Show when={split.subtext}>
{(subtext) => (
<span data-slot="tabs-v2-subtext" class="ml-2 text-xs text-text-weak">
<span data-slot="tabs-v2-subtext" class="ms-2 text-xs text-text-weak">
{subtext()}
</span>
)}
@@ -86,12 +87,13 @@ function TabsV2Trigger(props: ParentProps<TabsV2TriggerProps>) {
}
function TabsV2CloseButton(props: TabsV2CloseButtonProps) {
const i18n = useI18n()
const [split, rest] = splitProps(props, ["class", "classList", "onClick"])
return (
<div
role="button"
tabindex={0}
aria-label="Close tab"
aria-label={i18n.t("ui.tabs.close")}
data-slot="tabs-v2-close-button"
{...rest}
classList={{
@@ -1,5 +1,6 @@
import { type ComponentProps, type JSX, Show, splitProps } from "solid-js"
import { Icon } from "./icon"
import { useI18n } from "../../context/i18n"
import "./text-input-v2.css"
export interface TextInputV2Props extends Omit<ComponentProps<"input">, "type"> {
@@ -25,6 +26,7 @@ export interface TextInputV2Props extends Omit<ComponentProps<"input">, "type">
}
export function TextInputV2(props: TextInputV2Props) {
const i18n = useI18n()
const [local, inputProps] = splitProps(props, [
"class",
"classList",
@@ -71,7 +73,11 @@ export function TextInputV2(props: TextInputV2Props) {
type="button"
data-slot="text-input-v2-icon-button"
data-variant={local.showClearButton ? "clear" : "copy"}
aria-label={local.showClearButton ? (local.clearLabel ?? "Clear") : (local.copyLabel ?? "Copy")}
aria-label={
local.showClearButton
? (local.clearLabel ?? i18n.t("ui.common.clear"))
: (local.copyLabel ?? i18n.t("ui.message.copy"))
}
disabled={local.disabled}
onMouseDown={(event) => {
if (!local.showClearButton) return
+5 -2
View File
@@ -2,12 +2,14 @@ import { Toaster, toast, type ToasterProps } from "solid-sonner"
import type { ComponentProps, JSX } from "solid-js"
import { createContext, onCleanup, onMount, splitProps, useContext } from "solid-js"
import { Portal } from "solid-js/web"
import { useI18n } from "../../context/i18n"
import "./button-v2.css"
import "./toast-v2.css"
export interface ToastV2RegionProps extends ToasterProps {}
function ToastV2Region(props: ToastV2RegionProps) {
const i18n = useI18n()
const [local, rest] = splitProps(props, ["class", "className", "style", "toastOptions", "swipeDirections"])
onMount(() => {
const sync = () => {
@@ -56,7 +58,7 @@ function ToastV2Region(props: ToastV2RegionProps) {
...local.toastOptions,
unstyled: true,
closeButton: true,
closeButtonAriaLabel: local.toastOptions?.closeButtonAriaLabel ?? "Dismiss",
closeButtonAriaLabel: local.toastOptions?.closeButtonAriaLabel ?? i18n.t("ui.common.dismiss"),
}}
{...rest}
/>
@@ -96,13 +98,14 @@ function ToastV2Actions(props: ComponentProps<"div">) {
}
function ToastV2CloseButton(props: ComponentProps<"button">) {
const i18n = useI18n()
const toastId = useContext(ToastV2Context)
const [local, rest] = splitProps(props, ["children", "onClick"])
return (
<button
type="button"
data-slot="toast-v2-close-button"
aria-label="Dismiss"
aria-label={i18n.t("ui.common.dismiss")}
{...rest}
onClick={(event) => {
if (typeof local.onClick === "function") local.onClick(event)