Skip to content

feat(cli): extract gt-vue messages - #2013

Open
eoinest wants to merge 33 commits into
irisfrom
e/cli/add-vue-extraction
Open

feat(cli): extract gt-vue messages#2013
eoinest wants to merge 33 commits into
irisfrom
e/cli/add-vue-extraction

Conversation

@eoinest

@eoinest eoinest commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add @generaltranslation/vue-extractor as a standalone published package, parallel to the Python extractor. The package owns Vue SFC/script/compiler semantics; the gt CLI owns discovery, I/O, hashing, deduplication, and command behavior.
  • Keep the CLI integration to a thin lazy-loaded adapter so React-only commands do not load the Vue compiler graph.
  • Extract T, Var, formatter placeholders, Branch, Plural, useGT, useMessages, and msg from script setup, combined script blocks, Options API setup returns, aliases, namespaces, CommonJS, and statically resolvable expressions.
  • Match Vue compiler behavior for whitespace, delimiters, slots, directives, scope, and component-name normalization; resolve static Vite/Nuxt compiler settings and fail closed when hash parity or cooked template text cannot be guaranteed.
  • Detect mixed React/Vue workspaces, peer/optional dependencies, root and Nuxt-style Vue layouts, and preserve existing catalogs whenever parsing or configuration is incomplete.
  • Generate a Vue CDN loader during setup, document loadTranslations wiring, and make the deliberate fail-closed validation versus file-only stage behavior explicit.

Testing

  • @generaltranslation/vue-extractor: 37 files / 1,164 tests
  • gt: 124 files / 2,239 tests
  • Forced dependency build/typecheck: 8/8 tasks passed
  • Root library-default, lint, format, and diff gates — passed
  • Shared React/Vue/extractor wire-format fixtures — 4 exact source/hash contracts passed
  • Packed Node 20 and 24 package imports and public/private export checks — passed
  • Packed Vue 3.3/Vite 5 and Vue 3.5/Vite 7 consumers — passed generate, validate, exact runtime hash lookup, vue-tsc, SSR, and production builds
  • Mixed React/Vue monorepo, peer-only app, Nuxt discovery, custom compiler config, and fail-closed catalog-preservation cases — passed
  • Tracked Vite example — 21/21 catalog entries reproduced with zero diagnostics, including Vue TSX

Notes

Greptile Summary

This PR adds @generaltranslation/vue-extractor as a new standalone package and wires it into the gt CLI through a lazy-loaded adapter, enabling extraction of Vue SFC/script/template translations in parallel with the existing React and Python extractors.

  • New package (packages/vue-extractor): A 12,500-line static analyzer that parses Vue SFCs (template + script/script-setup + Options API), resolves GT component aliases, handles JSX, and matches Vue compiler whitespace/delimiter behavior for hash parity — without ever executing project code.
  • CLI integration (packages/cli): Adds Vue-aware workspace discovery, per-scope compiler-option resolution from Vite/Nuxt configs, atomic file creation with symlink and path-traversal guards, fail-closed validation for Vue, and a Vue setup wizard that installs gt-vue, generates loadTranslations.js, and configures credentials with the correct VITE_ prefix.

Confidence Score: 5/5

  • The change is safe to merge into its stack branch. All new extraction paths are fail-closed, generated files are written atomically, and workspace discovery is boundary-checked at every step.
  • The Vue extractor, CLI adapter, workspace discovery, compiler-option resolver, and file-generation paths are all well-guarded. The fail-closed behavior for Vue validation (exit on empty results) and the provenance-probe multi-pass for standalone JS files are correct and intentional. The only findings are style-level: duplicated helpers between the two loader-generation files, redundant filesystem I/O per library in the multi-library extraction loop, and a missing return before a never-typed call in validateProject. None of these affect runtime correctness.
  • No files require special attention before merging into the stack branch.

Important Files Changed

Filename Overview
packages/vue-extractor/src/internal/extractFromVueSource.ts Core extraction entry point. Fail-closed on SFC parse errors, production/development comment-parity check, and unsupported template/script languages. The provenance-probe multi-pass for standalone JS files is careful and well-guarded.
packages/vue-extractor/src/internal/script/analyze.ts 12,500-line static analyzer. Complex but well-structured; alias resolution, Options API binding, JSX, and uncertainty tracking are all present. Large file size makes it hard to audit fully, but the test suite is comprehensive.
packages/vue-extractor/src/internal/config/resolveVueCompilerOptions.ts Static Vite/Nuxt config resolution without execution. Correctly errors on ambiguous (both Nuxt + Vite) configs, path-traversal in explicit paths, and dynamic options it can't safely resolve.
packages/cli/src/vue/parse/createVueInlineUpdates.ts Thin CLI adapter: workspace-scoped compiler resolution, file matching, atomic hash/dedup pass. Fail-closed on compiler-option errors before extraction begins.
packages/cli/src/extraction/inlineSourceScopes.ts BFS workspace discovery for Vue local-dependent barrel packages. Logic is correct; selectVueWorkspacePackages properly seeds from direct gt-vue owners then follows reverse dependency edges.
packages/cli/src/extraction/createInlineUpdatesForLibrary.ts Lazy-loaded Vue adapter and multi-library orchestration. Correctly excludes *.vue from non-Vue parsers and runs deduplication across all library results.
packages/cli/src/fs/createLoadTranslationsFile.ts Significant hardening: symlink detection, lexical + real-path boundary checks, and atomic publishNewFile replaces the old existsSync+writeFile. Well-guarded against path-traversal.
packages/cli/src/fs/createRemoteLoadTranslationsFile.ts New CDN loader generator for Vue projects. Parallel safety checks to createLoadTranslationsFile; duplicates several helper functions that could be shared.
packages/cli/src/fs/determineFramework/index.ts Extended library detection with Vue priority, peer/optional dependency fallback, and workspace-aggregate detection. Priority order and additional-module logic are consistent.
packages/cli/src/fs/determineFramework/workspacePackages.ts New workspace manifest reader with robust symlink, node_modules, and path-traversal guards for both npm/Yarn and pnpm workspace formats.
packages/cli/src/cli/base.ts Vue setup wizard: installs gt-vue, creates loader, sets VITE_ credentials prefix, guards against unsupported Nuxt auto-setup. Logic for isVite/isVue flags and the !isCLIInstalled condition are correct.
packages/cli/src/translation/validate.ts Correctly extends validation to Vue and mixed projects; fail-closed exit for Vue on empty results is intentional and documented. logErrorAndExit without return is valid (returns never).
packages/cli/src/fs/publishNewFile.ts Atomic write-then-link pattern with O_EXCL-style no-clobber semantics and temp-file cleanup. EEXIST races call the validator callback. Well implemented.
packages/cli/src/setup/detectFramework.ts Nuxt and Vue+Vite detection added before generic Vite check. Disambiguation logic (hasVuePlugin && !hasReactPlugin when both frameworks present) is reasonable.

Sequence Diagram

sequenceDiagram
    participant CLI as gt CLI (VueCLI / InlineCLI)
    participant CIUFL as createInlineUpdatesForLibraries
    participant CVIU as createVueInlineUpdates
    participant ISS as inlineSourceScopes
    participant RVCO as resolveVueCompilerOptions
    participant EFVS as extractFromVueSource (vue-extractor)
    participant PP as postProcess (hash + dedup)

    CLI->>CIUFL: [GT_VUE, ...others], filePatterns, flags
    CIUFL->>ISS: readInlineSourceScopes(cwd, library)
    ISS-->>CIUFL: scopes[] (workspace BFS for Vue)
    CIUFL->>CIUFL: "exclude *.vue from non-Vue patterns"
    par Vue extraction
        CIUFL->>CVIU: filePatterns (Vue-specific)
        CVIU->>ISS: readInlineSourceScopes + readDefaultInlineSourcePatterns
        ISS-->>CVIU: scopes[]
        CVIU->>RVCO: resolveVueCompilerOptions(scope, viteConfigPath?)
        RVCO-->>CVIU: compilerOptions or errors[]
        alt errors present
            CVIU-->>CIUFL: "{updates:[], errors, warnings:[]}"
        else no errors
            loop each .vue / .js / .ts file
                CVIU->>EFVS: "extractFromVueSource(source, file, {compilerOptions, requireGTProvenance})"
                EFVS-->>CVIU: "{results, errors, warnings}"
            end
            CVIU->>PP: calculateHashes + dedupeUpdates
            CVIU-->>CIUFL: "{updates, errors, warnings}"
        end
    and React/other extraction
        CIUFL->>CIUFL: createInlineUpdates (existing React path)
    end
    CIUFL->>CIUFL: flatMap results, dedupeUpdates (cross-library)
    CIUFL-->>CLI: "{updates, errors, warnings}"
Loading

Reviews (20): Last reviewed commit: 2735158 | Re-trigger Greptile

@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
generaltranslation 18.09 KB (0%)
generaltranslation/runtime 14.87 KB (0%)
generaltranslation/id 2.55 KB (0%)
generaltranslation/internal 7.36 KB (0%)
generaltranslation/types 115 B (0%)
generaltranslation/errors 81 B (0%)
@generaltranslation/format 9.5 KB (0%)
@generaltranslation/format/types 89 B (0%)
@generaltranslation/format/internal 880 B (0%)
gt-i18n 11.96 KB (0%)
gt-i18n/types 13 B (0%)
gt-i18n/internal 22.4 KB (0%)
gt-i18n/internal/cookies 228 B (0%)
gt-i18n/internal/string 2.9 KB (0%)
gt-i18n/internal/types 13 B (0%)
@generaltranslation/react-core/pure 25.6 KB (0%)
@generaltranslation/react-core/hooks 20.6 KB (0%)
@generaltranslation/react-core/components 22.74 KB (0%)
@generaltranslation/react-core/components-rsc 26.19 KB (0%)
gt-react (client) 32.14 KB (0%)
gt-react (rsc) 28.71 KB (0%)
gt-react (server) 31.77 KB (0%)
gt-react/macros 8.81 KB (0%)
gt-vue 8.18 KB (0%)
gt-next (client) 44.2 KB (0%)
gt-next (rsc) 48.16 KB (0%)
gt-next (server) 44.31 KB (0%)
gt-next/config 270.72 KB (+0.18% 🔺)
gt-next/server 46.71 KB (0%)
gt-next/middleware 36.82 KB (0%)
gt-next/link 43.02 KB (0%)
gt-next/internal/_dictionary 144 B (0%)
gt-next/internal/_load-translations 144 B (0%)
gt-next/internal/_load-dictionary 144 B (0%)
gt-next/internal/_getLocale 125 B (0%)
gt-next/internal/_getRegion 122 B (0%)
gt-node 23.61 KB (0%)
gt-node/types 219 B (0%)
gt-node/internal 13.43 KB (0%)
gt-tanstack-start (client) 31.68 KB (0%)
gt-tanstack-start (server) 32.13 KB (0%)
gt-tanstack-start/server 10.27 KB (0%)
gt-react-native 30.11 KB (0%)
gt-react-native/plugin 4.6 KB (0%)
gt-react-native/internal 746 B (0%)

Comment thread packages/cli/src/vue/parse/script.ts Outdated
Comment thread packages/cli/src/vue/parse/script.ts Outdated
Comment thread packages/cli/src/extraction/createInlineUpdatesForLibrary.ts
@eoinest

eoinest commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

4 similar comments
@eoinest

eoinest commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest
eoinest force-pushed the e/cli/add-vue-extraction branch from 6b25a85 to ff312d4 Compare August 1, 2026 02:49
@eoinest

eoinest commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

2 similar comments
@eoinest

eoinest commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest
eoinest force-pushed the e/cli/add-vue-extraction branch from 7995c24 to c46120e Compare August 5, 2026 20:15
@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

1 similar comment
@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

archie-mckenzie
archie-mckenzie previously approved these changes Aug 6, 2026
@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

3 similar comments
@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest

eoinest commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@eoinest
eoinest force-pushed the e/cli/add-vue-extraction branch from 236ca99 to 9978985 Compare August 6, 2026 19:40
eoinest added 27 commits August 6, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants