import 'auto-i18n/placeholder'
// function i18nPlaceholder: (phase: string, fileName?: string) => string
const smile = 'ha ha'
// wrap phase needed translate
i18nPlaceholder(`pls translate this phase!`, {
translationFileName: 'common',
})
// => i18n('pls translate this phase!', {
// translationFileName: 'common',
// })
i18nPlaceholder(`pls translate this phase! ${smile}`, {
translationFileName: 'common',
i18nKey: 'pls',
})
// => i18n('pls', {
// translationFileName: 'common',
// args: {
// smile
// }
// })
i18nPlaceholder(`pls translate this phase! ${smile}`, {
translationFileName: 'common',
})
// => i18n('pls translate this phase! {{smile}}', {
// translationFileName: 'common',
// args: {
// smile
// }
// })
i18nPlaceholder(`pls translate this phase! ${(() => smile)()}`, {
translationFileName: 'common',
})
// => i18n('pls translate this phase! {{0}}', {
// translationFileName: 'common',
// args: {
// 0: smile
// }
// })
type CodeSection = {
start: number
end: number
code: string
}
type Collection = {
origin: CodeSection
target: CodeSection
translationFileName?: string
i18nKey?: string
key: string
}
type Collections = {
fileName: string
collections: Collection[]
}
function transformFiles: (fileNames: string[]) => Collections[]
function writeKeys: (collections: Collections[]) => void
- to reuse key, 'a{{b}}' and 'a{{1}}' treat as the same
function writeCache: (entries: string[]) => void
- build dependency graph for each entry, collect fileNames for each entry
- compare each file modified time with auto-i18n/modified.json
- ignore files which not changed
- collect collections from each changed files, write keys into auto-i18n/used-[entry].json
// auto-i18n/modified.json (git ignored)
{
'some/file': {
modified: '2000-01-01'
}
}
// auto-i18n/used-[entry].json
[
{
'pls': {
translationFileName: 'common'
}
}
]
- read auto-i18n/used-[entry].json and collect used keys opts
- collect key-value pairs from translation file(s) based on used keys opts
type Ignore = {
files?: (string | RegExp)[] // /type\.ts|(.+\.d\.ts)/
kinds?: number[] // [EnumDeclaration, InterfaceDeclaration, TypeLiteral, TypeParameter, TypeReference, TypeAliasDeclaration, ElementAccessExpression, ModuleDeclaration]
rules?: ((node: Node, ancestors: Node[]) => boolean)[] // [(node) => node.expression?.name === 'log' || node.expression?.escapedText === 'log']
comments?: string[] // ['i18n ignore']
}
type I18N = {
path: string // './public/locale/en'
defaultFileName: string // 'auto-i18n.json'
}
type Match = {
// contexts?: number[][] // [[ArrowFunction, Block], [FunctionDeclaration, Block]]
nodes?: ((node: Node, ancestors: Node[]) => boolean)[] // [(node) => node.expression?.name === 'i18nPlaceholder' || node.expression?.escapedText === 'i18nPlaceholder']
placeholder?: string // i18nPlaceholder
rule
}
type Transform = {
arg: (node: Node, index: number) => string // (node, index) => getIdentifier(node)?.escapedText.trim() || index
transformers: ((node: Node) => Node)[] // wrapped targeted node
}
type Setting = Ignore & I18N & Match
type Context = {
ancestors: Node[]
ignoreAll: boolean
}