@voerkai18n/utils
Version:
utils for voerkai18n
142 lines (127 loc) • 5.42 kB
text/typescript
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
}