wip(docs): i18n (#12681)
This commit is contained in:
@@ -1,16 +1,55 @@
|
||||
import { createSignal, onCleanup, splitProps } from "solid-js"
|
||||
import { createContext, createSignal, onCleanup, splitProps, useContext } from "solid-js"
|
||||
import type { JSX } from "solid-js/jsx-runtime"
|
||||
import { IconCheckCircle, IconHashtag } from "../icons"
|
||||
|
||||
export type ShareMessages = { locale: string } & Record<string, string>
|
||||
|
||||
const shareContext = createContext<ShareMessages>()
|
||||
|
||||
export function ShareI18nProvider(props: { messages: ShareMessages; children: JSX.Element }) {
|
||||
return <shareContext.Provider value={props.messages}>{props.children}</shareContext.Provider>
|
||||
}
|
||||
|
||||
export function useShareMessages() {
|
||||
const value = useContext(shareContext)
|
||||
if (value) {
|
||||
return value
|
||||
}
|
||||
throw new Error("ShareI18nProvider is required")
|
||||
}
|
||||
|
||||
export function normalizeLocale(locale: string) {
|
||||
return locale === "root" ? "en" : locale
|
||||
}
|
||||
|
||||
export function formatNumber(value: number, locale: string) {
|
||||
return new Intl.NumberFormat(normalizeLocale(locale)).format(value)
|
||||
}
|
||||
|
||||
export function formatCurrency(value: number, locale: string) {
|
||||
return new Intl.NumberFormat(normalizeLocale(locale), {
|
||||
style: "currency",
|
||||
currency: "USD",
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
}).format(value)
|
||||
}
|
||||
|
||||
export function formatCount(value: number, locale: string, singular: string, plural: string) {
|
||||
const unit = value === 1 ? singular : plural
|
||||
return `${formatNumber(value, locale)} ${unit}`
|
||||
}
|
||||
|
||||
interface AnchorProps extends JSX.HTMLAttributes<HTMLDivElement> {
|
||||
id: string
|
||||
}
|
||||
export function AnchorIcon(props: AnchorProps) {
|
||||
const [local, rest] = splitProps(props, ["id", "children"])
|
||||
const [copied, setCopied] = createSignal(false)
|
||||
const messages = useShareMessages()
|
||||
|
||||
return (
|
||||
<div {...rest} data-element-anchor title="Link to this message" data-status={copied() ? "copied" : ""}>
|
||||
<div {...rest} data-element-anchor title={messages.link_to_message} data-status={copied() ? "copied" : ""}>
|
||||
<a
|
||||
href={`#${local.id}`}
|
||||
onClick={(e) => {
|
||||
@@ -32,7 +71,7 @@ export function AnchorIcon(props: AnchorProps) {
|
||||
<IconHashtag width={18} height={18} />
|
||||
<IconCheckCircle width={18} height={18} />
|
||||
</a>
|
||||
<span data-element-tooltip>Copied!</span>
|
||||
<span data-element-tooltip>{messages.copied}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -59,19 +98,33 @@ export function createOverflow() {
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDuration(ms: number): string {
|
||||
export function formatDuration(ms: number, locale: string): string {
|
||||
const normalized = normalizeLocale(locale)
|
||||
const ONE_SECOND = 1000
|
||||
const ONE_MINUTE = 60 * ONE_SECOND
|
||||
|
||||
if (ms >= ONE_MINUTE) {
|
||||
const minutes = Math.floor(ms / ONE_MINUTE)
|
||||
return minutes === 1 ? `1min` : `${minutes}mins`
|
||||
return new Intl.NumberFormat(normalized, {
|
||||
style: "unit",
|
||||
unit: "minute",
|
||||
unitDisplay: "narrow",
|
||||
maximumFractionDigits: 0,
|
||||
}).format(Math.floor(ms / ONE_MINUTE))
|
||||
}
|
||||
|
||||
if (ms >= ONE_SECOND) {
|
||||
const seconds = Math.floor(ms / ONE_SECOND)
|
||||
return `${seconds}s`
|
||||
return new Intl.NumberFormat(normalized, {
|
||||
style: "unit",
|
||||
unit: "second",
|
||||
unitDisplay: "narrow",
|
||||
maximumFractionDigits: 0,
|
||||
}).format(Math.floor(ms / ONE_SECOND))
|
||||
}
|
||||
|
||||
return `${ms}ms`
|
||||
return new Intl.NumberFormat(normalized, {
|
||||
style: "unit",
|
||||
unit: "millisecond",
|
||||
unitDisplay: "narrow",
|
||||
maximumFractionDigits: 0,
|
||||
}).format(ms)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user