Skip to content

Commit fa18a28

Browse files
authored
Merge pull request #1 from lingodotdev/dev
feat: turbopack support
2 parents 5ebe65f + 210aefb commit fa18a28

File tree

182 files changed

+39869
-1607
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+39869
-1607
lines changed

cmp/.github/workflows/ci.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches: [main, dev]
6+
7+
jobs:
8+
lint:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v5.0.1
12+
# pnpm version is taken from package.json
13+
- name: Install pnpm
14+
uses: pnpm/action-setup@v4
15+
- name: Use Node.js 20
16+
uses: actions/setup-node@v6.0.0
17+
with:
18+
node-version: 20
19+
cache: "pnpm"
20+
- name: Install dependencies
21+
run: pnpm install
22+
- name: Lint
23+
run: pnpm lint:check
24+
- name: Check formatting
25+
run: pnpm format:check
26+
27+
test:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v5.0.1
31+
# pnpm version is taken from package.json
32+
- name: Install pnpm
33+
uses: pnpm/action-setup@v4
34+
- name: Use Node.js 20
35+
uses: actions/setup-node@v6.0.0
36+
with:
37+
node-version: 20
38+
cache: "pnpm"
39+
- name: Install dependencies
40+
run: pnpm install
41+
- name: Build
42+
run: pnpm build
43+
- name: Test
44+
run: pnpm test

cmp/.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
./node_modules/.bin/nano-staged

cmp/.prettierignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pnpm-lock.yaml
2+
.changeset/
3+
packages/cli/demo/
4+
build/
5+
dist/
6+
.react-router/
7+
.turbo/
8+
.next/
9+
CLAUDE.md

cmp/.prettierrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"trailingComma": "all",
3+
"singleQuote": false,
4+
"semi": true,
5+
"printWidth": 80,
6+
"tabWidth": 2,
7+
"useTabs": false
8+
}

cmp/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
1-
# LingoDev Compiler
1+
# Lingo.dev compiler
2+
3+
### Development
4+
5+
`pnpm install` from project root
6+
`pnpm turbo dev --filter=@lingo.dev/compile` to compile and watch for compiler changes
7+
8+
Choose the demo you want to work with and run it from the corresponding folder.
9+
`tsdown` in compiler is configured to cleanup the output folder before compilation, which works fine with next, but vite
10+
seems to be dead every time and has to be restarted.

cmp/compiler/README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# @lingo.dev/compiler
2+
3+
Official Lingo.dev compiler with automatic translation support for React applications.
4+
5+
This package provides plugins for multiple bundlers (Vite, Webpack, Rollup, esbuild) and a Next.js loader that
6+
automatically transforms React components to inject translation calls. It uses a hash-based metadata system to track
7+
translatable text across your application.
8+
9+
## Features
10+
11+
- **Automatic JSX text transformation** - Automatically detects and transforms translatable text in JSX
12+
- **Hash-based metadata** - Generates unique hashes for each translatable text based on content, component name, and
13+
file path
14+
- **Opt-in or automatic** - Configure whether to require `'use i18n'` directive or transform all files
15+
- **Multi-bundler support** - Works with Vite, Webpack, Rollup, esbuild, and Next.js
16+
- **Built on unplugin** - Unified plugin API across all bundlers
17+
- **Metadata tracking** - Maintains `.lingo/metadata.json` with all translatable content
18+
- **Translation server** - On-demand translation generation during development
19+
- **AI-powered translations** - Support for multiple LLM providers and Lingo.dev Engine
20+
21+
## Installation
22+
23+
```bash
24+
npm install @lingo.dev/compiler
25+
# or
26+
pnpm add @lingo.dev/compiler
27+
# or
28+
yarn add @lingo.dev/compiler
29+
```
30+
31+
## Structure
32+
33+
The compiler is organized into several key modules:
34+
35+
### Core Directories
36+
37+
#### `src/plugin/` - Build-time transformation
38+
39+
- **`transform/`** - Babel AST transformation logic for JSX text extraction
40+
- **`unplugin.ts`** - Universal plugin implementation (Vite, Webpack)
41+
- **`next.ts`** - Next.js-specific plugin with Turbopack and Webpack support
42+
- **`build-translator.ts`** - Batch translation generation at build time
43+
- **`virtual-modules-code-generator.ts`** - Generates code for virtual modules, dev config and locale resolvers for client and server
44+
45+
#### `src/metadata/` - Translation metadata management
46+
47+
- **`manager.ts`** - CRUD operations for `.lingo/metadata.json`
48+
- Thread-safe metadata file operations with file locking
49+
- Manages translation entries with hash-based identifiers
50+
51+
#### `src/translators/` - Translation provider abstraction
52+
53+
- **`lcp/`** - Lingo.dev Engine integration
54+
- **`pseudotranslator/`** - Development-mode fake translator
55+
- **`pluralization/`** - Automatic ICU MessageFormat detection
56+
- **`translator-factory.ts`** - Provider selection and initialization
57+
58+
#### `src/translation-server/` - Development server
59+
60+
- **`translation-server.ts`** - HTTP server for on-demand translations
61+
- **`cli.ts`** - Standalone CLI for translation generation
62+
- WebSocket support for real-time dev widget updates
63+
- Port management (60000-60099 range)
64+
65+
#### `src/react/` - Runtime translation hooks
66+
67+
- **`client/`** - Client-side Context-based hooks
68+
- **`server/`** - Server component cache-based hooks (isomorphic)
69+
- **`server-only/`** - Async server-only API (`getServerTranslations`)
70+
- **`shared/`** - Shared utilities (RichText rendering, Context)
71+
- **`next/`** - Next.js-specific middleware and locale switcher
72+
73+
#### `src/utils/` - Shared utilities
74+
75+
- **`hash.ts`** - Stable hash generation for translation keys
76+
- **`config-factory.ts`** - Configuration defaults and merging
77+
- **`logger.ts`** - Structured logging utilities
78+
- **`path-helpers.ts`** - File path resolution
79+
80+
#### `src/widget/` - Development widget
81+
82+
- In-browser translation editor overlay for development mode
83+
84+
### Support Directories
85+
86+
#### `tests/` - End-to-end testing
87+
88+
- **`e2e/`** - Playwright tests for full build workflows
89+
- **`fixtures/`** - Test applications (Vite, Next.js)
90+
- **`helpers/`** - Test utilities and assertions
91+
92+
#### `benchmarks/` - Performance benchmarks
93+
94+
- Translation speed benchmarks
95+
- Metadata I/O performance tests
96+
97+
#### `old-docs/` - Legacy documentation
98+
99+
- Historical design documents and notes
100+
101+
### Entry Points
102+
103+
- **`src/index.ts`** - Main package exports (plugins, types)
104+
- **`src/types.ts`** - Core TypeScript types
105+
106+
## Contributing
107+
108+
This is a beta package under active development. Feedback and contributions are welcome!
109+
110+
## License
111+
112+
ISC

cmp/compiler/Requirements.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
## Requirements
2+
3+
1. The core thing is DX. We want compiler to work as seamless as possible.
4+
2. It should work at least with turbopack (since it's next default bundler), webpack and vite.
5+
3. HMR should work, whenever we update the code the state of the app should be kept as it owuld be without the compiler.
6+
4. There should be a way to override the translations
7+
5. We should be able to translate the attributes, the most obvious ones are alt and aria-label, aria-description and
8+
such, but we may also add a way to translate other string attributes too.
9+
6. We should keep translations calls to the minimum.
10+
7. We start with react, but it would be nice to apply the same approach to other frameworks. Like vue and astro. So the
11+
system should be flexible.
12+
8. The translations should be possible to commit in the repo, so we can version them. Maybe we can also consider
13+
conforming to the existing standard?
14+
15+
## Overall architecture
16+
17+
Given that we still may want translations in the dev mode, but we want to keep them to minimum and do not interfere with
18+
the development flow, we may consider the following approach:
19+
20+
1. Do not translate the text unless explicitly requested.
21+
2. Allow using pseudolocalization for even more simple checks. It shows which part of the UI can be translated by
22+
compiler, and also using varying width of the text highlights part of the interface not ready for varying languages.
23+
24+
This leads us to the question, how to lazily request the translations in the dev mode.
25+
Let's work with the SPA apps as an example (since SSR apps may have more options).
26+
Both currently rendered components and the locale are client side.
27+
Cache for translations is stored in the filesystem in the project.
28+
So the way to receive a request from the browser to the host that will get the translations and store the cache.
29+
30+
The most straightforward way to do this is to use the usual web server. App will send a request for translations when needed,
31+
server components can do the same. This adds a bit of latency but keeps the code uniform.
32+
33+
With this approach we get couple more questions:
34+
35+
- How to start the server
36+
- How to make the client aware about server's address
37+
- How to batch the calls, both client and server side.
38+
39+
How to start the server
40+
While it sounds simple, it's not that simple if you don't want to create any external scripts.
41+
We have at least three environments:
42+
43+
- Next turbopack: no startup hooks.
44+
- Next webpack: there is compiler.hooks.watchRun. Well, watchRun runs on every script compilation during hot reload.
45+
- Vite: buildStart.
46+
47+
So next with turbopack is the most complex case.
48+
49+
It shows which part of the UI can be translated by
50+
compiler - can be done easier? Add some colors

0 commit comments

Comments
 (0)