feat: setting sidebar titles i18n

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-09-11 20:46:30 +08:00
parent 13858762b4
commit 39f84cdaff
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
21 changed files with 90 additions and 47 deletions

View File

@ -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",

View File

@ -0,0 +1,5 @@
{
"confirm": "Confirm",
"ok": "OK",
"cancel": "Cancel"
}

View File

@ -0,0 +1,5 @@
{
"confirm": "确认",
"ok": "好",
"cancel": "取消"
}

View File

@ -11,6 +11,17 @@
"sign_in_to": "登录到"
},
"settings": {
"titles": {
"general": "常规",
"appearance": "外观",
"actions": "操作",
"integration": "集成",
"about": "关于",
"profile": "个人资料",
"shortcuts": "热键",
"power": "Power",
"invitations": "邀请"
},
"general": {
"app": "应用程序",
"data_persist": {

View File

@ -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

View File

@ -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 {}

View File

@ -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", "")

View File

@ -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

View File

@ -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>
)
}

View File

@ -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,
})

View File

@ -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 />

View File

@ -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,
})

View File

@ -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,
})

View File

@ -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,
})

View File

@ -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,
})

View File

@ -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,
})

View File

@ -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,
})

View File

@ -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() {

View File

@ -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`,
})