UNPKG

@voerkai18n/utils

Version:

utils for voerkai18n

142 lines (127 loc) 5.42 kB
import type { VoerkaI18nSettings } from "@voerkai18n/runtime" import { getLanguageDir } from "./getLanguageDir" import { getVoerkaI18nSettings } from "./getVoerkaI18nSettings" import { getPackageModuleType } from "flex-tools/package/getPackageModuleType" import { isTypeScriptPackage } from "flex-tools/package/isTypeScriptPackage" import { readFile } from "flex-tools/fs/nodefs" import path from "node:path" import fs from "node:fs" export type VoerkaI18nProjectContext= VoerkaI18nSettings & { rootDir : string langDir : string langRelDir : string settingFile : string settingRelFile : string typescript : boolean moduleType : "esm" | "cjs" | undefined promptDir : string getTranslateMessagesDir : (autoCreate?:boolean)=>string getTranslateParagraphsDir: (autoCreate?:boolean)=>string getMessagesDir : (autoCreate?:boolean)=>string getParagraphsDir : (autoCreate?:boolean)=>string getPrompt : (name:string)=>Promise<string> getApi : (name:string,defaultValue?:Record<string,any>)=>Record<string,any> | undefined api : Record<string,any> | undefined } async function getPromptTemplate(this:VoerkaI18nProjectContext,name:string,defaultPrompt?:string){ const { promptDir } = this; if(!name) return defaultPrompt const promptFile = path.isAbsolute(name) ? name : path.join(promptDir,name.endsWith(".md") ? name : name+".md"); if(fs.existsSync(promptFile)){ return await readFile(promptFile,{ encoding: "utf-8" }); } return defaultPrompt } function getDefaultPatterns(this:VoerkaI18nProjectContext,options?:Record<string,any>){ const patterns = [ "!coverage", "!.pnpm", "!**/*.test.*", "!**/*.spec.*", "!.vscode", "!dist", "!.git", "!.turbo", "!**/*.d.ts", "!*.config.{js,ts}", "!node_modules", "!"+this.langRelDir ] if(Array.isArray(this.patterns)){ patterns.push(...this.patterns) } if(Array.isArray(options?.patterns)){ patterns.push(...options.patterns) delete options.patterns }else if(typeof(options?.patterns)==='string'){ patterns.push(options.patterns) delete options.patterns } // 如果所有的patterns都是排除模式,则添加默认的包含模式 if(patterns.every(p=>p.startsWith("!"))){ patterns.push("**/*.{js,jsx,ts,tsx,vue,astro,svelte,mdx}") } return patterns } function getApi(this:VoerkaI18nProjectContext,name:string,defaultValue?:Record<string,any>){ const { langDir } = this; const apiFile= path.join(langDir,"api.json") let apis:Record<string,any> = {} try{ if(fs.existsSync(apiFile)){ apis = JSON.parse(fs.readFileSync(apiFile,"utf-8")) } }catch{} return apis[name] || defaultValue } function getApiParams(this:VoerkaI18nProjectContext,options?:Record<string,any>){ if(typeof(options)==='object'){ let api:Record<string,any> | undefined if(typeof(options.api)==='string'){ api = getApi.call(this,options.api,{}) } Object.entries(options).forEach(([key,value])=>{ if(key.startsWith("api") && key.length>3){ const name = key.substring(3) if(!api) api = {} api[name[0].toLowerCase() + name.substring(1)] = value } }) return api } } function getDir(this:VoerkaI18nProjectContext,location:string){ return (autoCreate:boolean=true)=>{ const dir = path.join(this.langDir,location) if(autoCreate && !fs.existsSync(dir)){ fs.mkdirSync(dir,{recursive:true}) } return dir } } /** * * @param options * @returns */ export async function getProjectContext(options?:Record<string,any>) { const ctx = await getVoerkaI18nSettings() as VoerkaI18nProjectContext ctx.rootDir = process.env.INIT_CWD || process.cwd() ctx.langDir = getLanguageDir() ctx.langRelDir = path.relative(process.cwd(),ctx.langDir).replaceAll(path.sep,"/") ctx.settingFile = path.join(ctx.langDir, "settings.json") ctx.settingRelFile = path.relative(process.cwd(),ctx.settingFile).replace(/\\/g,'/') ctx.promptDir = path.join(ctx.langDir,"prompts") ctx.getPrompt = getPromptTemplate.bind(ctx) ctx.patterns = getDefaultPatterns.call(ctx,options) ctx.getApi = getApi.bind(ctx) ctx.getTranslateMessagesDir = getDir.call(ctx,"translates/messages").bind(ctx) ctx.getTranslateParagraphsDir = getDir.call(ctx,"translates/paragraphs").bind(ctx) ctx.getMessagesDir = getDir.call(ctx,"messages").bind(ctx) ctx.getParagraphsDir = getDir.call(ctx,"paragraphs").bind(ctx) if(!ctx.typescript) ctx.typescript = isTypeScriptPackage() if(!ctx.moduleType) ctx.moduleType = getPackageModuleType() Object.assign(ctx,options) ctx.api = getApiParams.call(ctx,options) return ctx }