feat: setting sidebar titles i18n
Signed-off-by: Innei <i@innei.in>
This commit is contained in:
parent
13858762b4
commit
39f84cdaff
|
|
@ -11,6 +11,17 @@
|
|||
"sign_in_to": "Sign in to"
|
||||
},
|
||||
"settings": {
|
||||
"titles": {
|
||||
"general": "General",
|
||||
"appearance": "Appearance",
|
||||
"actions": "Actions",
|
||||
"integration": "Integration",
|
||||
"about": "About",
|
||||
"profile": "Profile",
|
||||
"shortcuts": "Shortcuts",
|
||||
"power": "Power",
|
||||
"invitations": "Invitations"
|
||||
},
|
||||
"general": {
|
||||
"app": "App",
|
||||
"launch_at_login": "Launch at login",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"confirm": "Confirm",
|
||||
"ok": "OK",
|
||||
"cancel": "Cancel"
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"confirm": "确认",
|
||||
"ok": "好",
|
||||
"cancel": "取消"
|
||||
}
|
||||
|
|
@ -11,6 +11,17 @@
|
|||
"sign_in_to": "登录到"
|
||||
},
|
||||
"settings": {
|
||||
"titles": {
|
||||
"general": "常规",
|
||||
"appearance": "外观",
|
||||
"actions": "操作",
|
||||
"integration": "集成",
|
||||
"about": "关于",
|
||||
"profile": "个人资料",
|
||||
"shortcuts": "热键",
|
||||
"power": "Power",
|
||||
"invitations": "邀请"
|
||||
},
|
||||
"general": {
|
||||
"app": "应用程序",
|
||||
"data_persist": {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
import en from "../../../../locales/en.json"
|
||||
import lang_en from "../../../../locales/modules/lang/en.json"
|
||||
import lang_zhCN from "../../../../locales/modules/lang/zh_CN.json"
|
||||
import common_en from "../../../../locales/namespaces/common/en.json"
|
||||
import common_zhCN from "../../../../locales/namespaces/common/zh_CN.json"
|
||||
import lang_en from "../../../../locales/namespaces/lang/en.json"
|
||||
import lang_zhCN from "../../../../locales/namespaces/lang/zh_CN.json"
|
||||
import zhCN from "../../../../locales/zh_CN.json"
|
||||
|
||||
const resources = {
|
||||
en: {
|
||||
translation: en,
|
||||
lang: lang_en,
|
||||
common: common_en,
|
||||
},
|
||||
zh_CN: {
|
||||
translation: zhCN,
|
||||
lang: lang_zhCN,
|
||||
common: common_zhCN,
|
||||
},
|
||||
}
|
||||
export default resources
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import type { t } from "i18next"
|
||||
import type { FC, PropsWithChildren } from "react"
|
||||
|
||||
declare global {
|
||||
|
|
@ -28,6 +29,12 @@ declare global {
|
|||
}
|
||||
|
||||
export function tw(strings: TemplateStringsArray, ...values: any[]): string
|
||||
|
||||
export type I18nKeys = OmitStringType<Parameters<typeof t>[0]>
|
||||
|
||||
type IsLiteralString<T> = T extends string ? (string extends T ? never : T) : never
|
||||
|
||||
type OmitStringType<T> = T extends any[] ? OmitStringType<T[number]> : IsLiteralString<T>
|
||||
}
|
||||
|
||||
export {}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,8 @@ export const initI18n = async () => {
|
|||
lng: language,
|
||||
fallbackLng: fallbackLanguage,
|
||||
defaultNS,
|
||||
ns: [defaultNS],
|
||||
debug: true,
|
||||
resources,
|
||||
|
||||
backend: [],
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -32,16 +29,16 @@ if (import.meta.hot) {
|
|||
const resources = JSON.parse(content)
|
||||
|
||||
// `file` is absolute path e.g. /Users/innei/git/follow/locales/en.json
|
||||
// Absolute path e.g. /Users/innei/git/follow/locales/modules/<module-name>/en.json
|
||||
// Absolute path e.g. /Users/innei/git/follow/locales/namespaces/<module-name>/en.json
|
||||
|
||||
// 1. parse root language
|
||||
if (!file.includes("locales/modules")) {
|
||||
if (!file.includes("locales/namespaces")) {
|
||||
const lang = file.split("/").pop()?.replace(".json", "")
|
||||
if (!lang) return
|
||||
i18next.addResourceBundle(lang, defaultNS, resources, true, true)
|
||||
i18next.reloadResources(lang, defaultNS)
|
||||
} else {
|
||||
const nsName = file.match(/locales\/modules\/(.+?)\//)?.[1]
|
||||
const nsName = file.match(/locales\/namespaces\/(.+?)\//)?.[1]
|
||||
|
||||
if (!nsName) return
|
||||
const lang = file.split("/").pop()?.replace(".json", "")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ function getSettings() {
|
|||
const map = import.meta.glob("../../pages/settings/\\(settings\\)/*", { eager: true })
|
||||
|
||||
const settings = [] as {
|
||||
name: string
|
||||
name: I18nKeys
|
||||
iconName: string
|
||||
path: string
|
||||
Component: () => JSX.Element
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { cn } from "@renderer/lib/utils"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { useLoaderData } from "react-router-dom"
|
||||
|
||||
import { settings } from "./constants"
|
||||
|
|
@ -7,6 +8,7 @@ import type { SettingPageConfig } from "./utils"
|
|||
export const SettingsSidebarTitle = ({ path, className }: { path: string; className?: string }) => {
|
||||
const tab = settings.find((t) => t.path === path)
|
||||
|
||||
const { t } = useTranslation()
|
||||
if (!tab) {
|
||||
return null
|
||||
}
|
||||
|
|
@ -14,7 +16,7 @@ export const SettingsSidebarTitle = ({ path, className }: { path: string; classN
|
|||
return (
|
||||
<div className={cn("flex items-center gap-2 text-[0.94rem] font-medium", className)}>
|
||||
<i className={tab.iconName} />
|
||||
<span>{tab.name}</span>
|
||||
<span>{t(tab.name as any)}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
|
||||
export interface SettingPageConfig {
|
||||
iconName: string
|
||||
name: string
|
||||
name: I18nKeys
|
||||
priority: number
|
||||
headerIcon?: string
|
||||
}
|
||||
export const defineSettingPage = (config: SettingPageConfig) => () => ({
|
||||
export const defineSettingPageData = (config: SettingPageConfig) => () => ({
|
||||
...config,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { SettingAbout } from "@renderer/modules/settings/tabs/about"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName: "i-mgc-information-cute-re",
|
||||
name: "About",
|
||||
name: "settings.titles.about",
|
||||
priority: 9999,
|
||||
})
|
||||
export const Component = () => <SettingAbout />
|
||||
|
|
|
|||
|
|
@ -10,19 +10,19 @@ import type {
|
|||
} from "@renderer/models"
|
||||
import { ActionCard } from "@renderer/modules/settings/action-card"
|
||||
import { SettingsTitle } from "@renderer/modules/settings/title"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
import { Queries } from "@renderer/queries"
|
||||
import { useMutation } from "@tanstack/react-query"
|
||||
import { useEffect, useState } from "react"
|
||||
import { toast } from "sonner"
|
||||
|
||||
const iconName = "i-mgc-magic-2-cute-re"
|
||||
const name = "Actions"
|
||||
|
||||
const priority = 1020
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.actions",
|
||||
priority,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { SettingAppearance } from "@renderer/modules/settings/tabs/apperance"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = "i-mgc-palette-cute-re"
|
||||
const name = "Appearance"
|
||||
|
||||
const priority = 1010
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.appearance",
|
||||
priority,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { SettingGeneral } from "@renderer/modules/settings/tabs/general"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = "i-mgc-settings-7-cute-re"
|
||||
const name = "General"
|
||||
|
||||
const priority = 1000
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.general",
|
||||
priority,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { SettingIntegration } from "@renderer/modules/settings/tabs/integration"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = "i-mgc-department-cute-re"
|
||||
const name = "Integration"
|
||||
|
||||
const priority = 1025
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.integration",
|
||||
priority,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { SettingInvitations } from "@renderer/modules/settings/tabs/invitations"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = "i-mgc-heart-hand-cute-re"
|
||||
const name = "Invitations"
|
||||
|
||||
const priority = 1055
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.invitations",
|
||||
priority,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { ProfileSettingForm } from "@renderer/modules/profile/profile-setting-form"
|
||||
import { SettingsTitle } from "@renderer/modules/settings/title"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = "i-mgc-user-setting-cute-re"
|
||||
const name = "Profile"
|
||||
|
||||
const priority = 1030
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.profile",
|
||||
priority,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ import { KbdCombined } from "@renderer/components/ui/kbd/Kbd"
|
|||
import { shortcuts } from "@renderer/constants/shortcuts"
|
||||
import { cn } from "@renderer/lib/utils"
|
||||
import { SettingsTitle } from "@renderer/modules/settings/title"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = "i-mgc-hotkey-cute-re"
|
||||
const name = "Shortcuts"
|
||||
|
||||
const priority = 1040
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.shortcuts",
|
||||
priority,
|
||||
})
|
||||
export function Component() {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import { SettingWallet } from "@renderer/modules/settings/tabs/wallet"
|
||||
import { defineSettingPage } from "@renderer/modules/settings/utils"
|
||||
import { defineSettingPageData } from "@renderer/modules/settings/utils"
|
||||
|
||||
const iconName = `i-mgc-power-outline`
|
||||
const name = "Power"
|
||||
|
||||
const priority = 1050
|
||||
|
||||
export const loader = defineSettingPage({
|
||||
export const loader = defineSettingPageData({
|
||||
iconName,
|
||||
name,
|
||||
name: "settings.titles.power",
|
||||
priority,
|
||||
headerIcon: `i-mgc-power text-accent`,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue