diff --git a/src/frameworks/index.ts b/src/frameworks/index.ts index 817a8c4c..80ec1fe8 100644 --- a/src/frameworks/index.ts +++ b/src/frameworks/index.ts @@ -27,6 +27,7 @@ import GeneralFramework from './general' import LinguiFramework from './lingui' import JekyllFramework from './jekyll' import FluentVueSFCFramework from './fluent-vue-sfc' +import TypesafeI18nFramework from './typesafe-i18n' import i18n from '~/i18n' import { Log } from '~/utils' @@ -61,6 +62,7 @@ export const frameworks: Framework[] = [ new LinguiFramework(), new JekyllFramework(), new GeneralFramework(), + new TypesafeI18nFramework(), // Vue SFC and FluentVue SFC should be the last ones new VueSFCFramework(), diff --git a/src/frameworks/typesafe-i18n.ts b/src/frameworks/typesafe-i18n.ts new file mode 100644 index 00000000..9b2abd2a --- /dev/null +++ b/src/frameworks/typesafe-i18n.ts @@ -0,0 +1,74 @@ +import { TextDocument } from 'vscode' +import { Framework } from './base' +import { DetectionResult } from '~/core' +import { LanguageId } from '~/utils' + +class TypesafeI18nFramework extends Framework { + id = 'typesafe-i18n' + display = 'typesafe-i18n' + + monopoly = true + + detection = { + packageJSON: [ + 'typesafe-i18n', + ], + } + + enabledParsers = ['ts', 'js'] + + pathMatcher = () => '{locale}/index.{ext}' + + languageIds: LanguageId[] = [ + 'javascript', + 'typescript', + 'javascriptreact', + 'typescriptreact', + 'svelte', + 'html', + ] + + usageMatchRegex = [ + '\\$?LL\\.({key})\\(((\\{.*\\})|([^)]*))\\)', + ] + + perferredKeystyle = 'nested' as const + + perferredLocalePaths = ['src/i18n'] + + private replaceKeypath = (keypath: string, text: string) => + text.replace('$1', keypath.split('.').map(part => `['${part}']`).join('')) + + private getHtmlRefactorTemplates = (keypath: string, params: string) => [ + `{LL{key}(${params})}`, // other + `{$LL{key}(${params})}`, // svelte + ].map(text => this.replaceKeypath(keypath, text)) + + private getJavaScriptRefactorTemplates = (keypath: string, params: string) => [ + `LL{key}(${params})`, // other + `$LL{key}(${params})`, // svelte + ].map(text => this.replaceKeypath(keypath, text)) + + refactorTemplates(keypath: string, args: string[] = [], _doc?: TextDocument, detection?: DetectionResult) { + let params = '' + if (args.length) + params += `${args.join(', ')}` + + switch (detection?.source) { + case 'html-inline': + case 'html-attribute': + return this.getHtmlRefactorTemplates(keypath, params) + case 'js-string': + case 'js-template': + case 'jsx-text': + return this.getJavaScriptRefactorTemplates(keypath, params) + } + + return [ + ...this.getHtmlRefactorTemplates(keypath, params), + ...this.getJavaScriptRefactorTemplates(keypath, params), + ] + } +} + +export default TypesafeI18nFramework