mirror of
https://github.com/Molunerfinn/PicGo.git
synced 2026-10-19 16:14:41 +00:00
116 lines
3.2 KiB
TypeScript
116 lines
3.2 KiB
TypeScript
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import { parse } from 'yaml'
|
|
import type { Plugin } from 'vite'
|
|
|
|
const I18N_SOURCE_DIR = 'public/i18n'
|
|
const SOURCE_RELATIVE_PATH = `${I18N_SOURCE_DIR}/en.yml`
|
|
const UNIVERSAL_OUTPUT_RELATIVE_PATH = 'src/universal/types/i18n.d.ts'
|
|
const RENDERER_OUTPUT_RELATIVE_PATH = 'src/renderer/i18n/i18next.d.ts'
|
|
|
|
function formatKey (key: string) {
|
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key)
|
|
}
|
|
|
|
function readTranslationKeys (sourcePath: string) {
|
|
if (!fs.existsSync(sourcePath)) {
|
|
return []
|
|
}
|
|
|
|
const raw = fs.readFileSync(sourcePath, 'utf8')
|
|
const data = parse(raw)
|
|
|
|
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
return []
|
|
}
|
|
|
|
return Object.keys(data as Record<string, unknown>)
|
|
}
|
|
|
|
function buildUniversalTypeContent (keys: string[]) {
|
|
const uniqueKeys = Array.from(new Set(keys))
|
|
const lines = uniqueKeys.map((key) => ` ${formatKey(key)}: string`)
|
|
|
|
return `// This file is auto-generated by vite-plugin-i18n-types. Do not edit.
|
|
interface ILocales {
|
|
${lines.join('\n')}
|
|
}
|
|
|
|
type ILocalesKey = keyof ILocales
|
|
`
|
|
}
|
|
|
|
function buildRendererTypeContent () {
|
|
return `// This file is auto-generated by vite-plugin-i18n-types. Do not edit.
|
|
import "i18next"
|
|
|
|
declare module "i18next" {
|
|
interface CustomTypeOptions {
|
|
resources: {
|
|
translation: ILocales
|
|
}
|
|
}
|
|
}
|
|
`
|
|
}
|
|
|
|
function writeFileIfChanged (outputPath: string, nextContent: string) {
|
|
const previousContent = fs.existsSync(outputPath)
|
|
? fs.readFileSync(outputPath, 'utf8')
|
|
: ''
|
|
|
|
if (previousContent === nextContent) {
|
|
return
|
|
}
|
|
|
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true })
|
|
fs.writeFileSync(outputPath, nextContent, 'utf8')
|
|
}
|
|
|
|
function writeTypesFiles (sourcePath: string, universalOutputPath: string, rendererOutputPath: string) {
|
|
const keys = readTranslationKeys(sourcePath)
|
|
writeFileIfChanged(universalOutputPath, buildUniversalTypeContent(keys))
|
|
writeFileIfChanged(rendererOutputPath, buildRendererTypeContent())
|
|
}
|
|
|
|
export function i18nTypesPlugin (): Plugin {
|
|
let sourcePath = ''
|
|
let universalOutputPath = ''
|
|
let rendererOutputPath = ''
|
|
let projectRoot = ''
|
|
|
|
const generate = () => {
|
|
try {
|
|
writeTypesFiles(sourcePath, universalOutputPath, rendererOutputPath)
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : String(error)
|
|
console.error(`[vite-plugin-i18n-types] ${message}`)
|
|
}
|
|
}
|
|
|
|
return {
|
|
name: 'vite-plugin-i18n-types',
|
|
enforce: 'pre',
|
|
configResolved (config) {
|
|
projectRoot = path.resolve(config.root, '../..')
|
|
sourcePath = path.resolve(projectRoot, SOURCE_RELATIVE_PATH)
|
|
universalOutputPath = path.resolve(projectRoot, UNIVERSAL_OUTPUT_RELATIVE_PATH)
|
|
rendererOutputPath = path.resolve(projectRoot, RENDERER_OUTPUT_RELATIVE_PATH)
|
|
},
|
|
buildStart () {
|
|
generate()
|
|
},
|
|
configureServer (server) {
|
|
server.watcher.add(path.resolve(projectRoot, I18N_SOURCE_DIR))
|
|
},
|
|
handleHotUpdate ({ file }) {
|
|
const normalizedFile = path.resolve(file)
|
|
const normalizedSourceDir = path.resolve(path.dirname(sourcePath))
|
|
|
|
if (normalizedFile.startsWith(normalizedSourceDir)) {
|
|
generate()
|
|
}
|
|
}
|
|
}
|
|
}
|