#
tokens: 46048/50000 17/626 files (page 7/16)
lines: off (toggle) GitHub
raw markdown copy
This is page 7 of 16. Use http://codebase.md/lingodotdev/lingo.dev?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── README.md
├── .claude
│   ├── agents
│   │   └── code-architect-reviewer.md
│   └── commands
│       ├── analyze-bucket-type.md
│       └── create-bucket-docs.md
├── .editorconfig
├── .github
│   ├── dependabot.yml
│   └── workflows
│       ├── docker.yml
│       ├── lingodotdev.yml
│       ├── pr-check.yml
│       ├── pr-lint.yml
│       └── release.yml
├── .gitignore
├── .husky
│   └── commit-msg
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .vscode
│   ├── extensions.json
│   ├── launch.json
│   └── settings.json
├── action.yml
├── CLAUDE.md
├── CODE_OF_CONDUCT.md
├── commitlint.config.js
├── composer.json
├── content
│   ├── banner.compiler.png
│   ├── banner.dark.png
│   └── banner.launch.png
├── CONTRIBUTING.md
├── DEBUGGING.md
├── demo
│   ├── adonisjs
│   │   ├── .editorconfig
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── ace.js
│   │   ├── adonisrc.ts
│   │   ├── app
│   │   │   ├── exceptions
│   │   │   │   └── handler.ts
│   │   │   └── middleware
│   │   │       └── container_bindings_middleware.ts
│   │   ├── bin
│   │   │   ├── console.ts
│   │   │   ├── server.ts
│   │   │   └── test.ts
│   │   ├── CHANGELOG.md
│   │   ├── config
│   │   │   ├── app.ts
│   │   │   ├── bodyparser.ts
│   │   │   ├── cors.ts
│   │   │   ├── hash.ts
│   │   │   ├── inertia.ts
│   │   │   ├── logger.ts
│   │   │   ├── session.ts
│   │   │   ├── shield.ts
│   │   │   ├── static.ts
│   │   │   └── vite.ts
│   │   ├── eslint.config.js
│   │   ├── inertia
│   │   │   ├── app
│   │   │   │   ├── app.tsx
│   │   │   │   └── ssr.tsx
│   │   │   ├── css
│   │   │   │   └── app.css
│   │   │   ├── lingo
│   │   │   │   ├── dictionary.js
│   │   │   │   └── meta.json
│   │   │   ├── pages
│   │   │   │   ├── errors
│   │   │   │   │   ├── not_found.tsx
│   │   │   │   │   └── server_error.tsx
│   │   │   │   └── home.tsx
│   │   │   └── tsconfig.json
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── resources
│   │   │   └── views
│   │   │       └── inertia_layout.edge
│   │   ├── start
│   │   │   ├── env.ts
│   │   │   ├── kernel.ts
│   │   │   └── routes.ts
│   │   ├── tests
│   │   │   └── bootstrap.ts
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   ├── next-app
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── eslint.config.mjs
│   │   ├── next.config.ts
│   │   ├── package.json
│   │   ├── postcss.config.mjs
│   │   ├── public
│   │   │   ├── file.svg
│   │   │   ├── globe.svg
│   │   │   ├── next.svg
│   │   │   ├── vercel.svg
│   │   │   └── window.svg
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── app
│   │   │   │   ├── client-component.tsx
│   │   │   │   ├── favicon.ico
│   │   │   │   ├── globals.css
│   │   │   │   ├── layout.tsx
│   │   │   │   ├── lingo-dot-dev.tsx
│   │   │   │   ├── page.tsx
│   │   │   │   └── test
│   │   │   │       └── page.tsx
│   │   │   ├── components
│   │   │   │   ├── hero-actions.tsx
│   │   │   │   ├── hero-subtitle.tsx
│   │   │   │   ├── hero-title.tsx
│   │   │   │   └── index.ts
│   │   │   └── lingo
│   │   │       ├── dictionary.js
│   │   │       └── meta.json
│   │   └── tsconfig.json
│   ├── react-router-app
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── app
│   │   │   ├── app.css
│   │   │   ├── lingo
│   │   │   │   ├── dictionary.js
│   │   │   │   └── meta.json
│   │   │   ├── root.tsx
│   │   │   ├── routes
│   │   │   │   ├── home.tsx
│   │   │   │   └── test.tsx
│   │   │   ├── routes.ts
│   │   │   └── welcome
│   │   │       ├── lingo-dot-dev.tsx
│   │   │       ├── logo-dark.svg
│   │   │       ├── logo-light.svg
│   │   │       └── welcome.tsx
│   │   ├── Dockerfile
│   │   ├── package.json
│   │   ├── public
│   │   │   └── favicon.ico
│   │   ├── react-router.config.ts
│   │   ├── README.md
│   │   ├── tsconfig.json
│   │   └── vite.config.ts
│   └── vite-project
│       ├── .gitignore
│       ├── CHANGELOG.md
│       ├── eslint.config.js
│       ├── index.html
│       ├── package.json
│       ├── public
│       │   └── vite.svg
│       ├── README.md
│       ├── src
│       │   ├── App.css
│       │   ├── App.tsx
│       │   ├── assets
│       │   │   └── react.svg
│       │   ├── components
│       │   │   └── test.tsx
│       │   ├── index.css
│       │   ├── lingo
│       │   │   ├── dictionary.js
│       │   │   └── meta.json
│       │   ├── lingo-dot-dev.tsx
│       │   ├── main.tsx
│       │   └── vite-env.d.ts
│       ├── tsconfig.app.json
│       ├── tsconfig.json
│       ├── tsconfig.node.json
│       └── vite.config.ts
├── Dockerfile
├── i18n.json
├── i18n.lock
├── integrations
│   └── directus
│       ├── .gitignore
│       ├── CHANGELOG.md
│       ├── docker-compose.yml
│       ├── Dockerfile
│       ├── package.json
│       ├── README.md
│       ├── src
│       │   ├── api.ts
│       │   ├── app.ts
│       │   └── index.spec.ts
│       ├── tsconfig.json
│       ├── tsconfig.test.json
│       └── tsup.config.ts
├── ISSUE_TEMPLATE.md
├── legacy
│   ├── cli
│   │   ├── bin
│   │   │   └── cli.mjs
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   └── readme.md
│   └── sdk
│       ├── CHANGELOG.md
│       ├── index.d.ts
│       ├── index.js
│       ├── package.json
│       └── README.md
├── LICENSE.md
├── mcp.md
├── package.json
├── packages
│   ├── cli
│   │   ├── assets
│   │   │   ├── failure.mp3
│   │   │   └── success.mp3
│   │   ├── bin
│   │   │   └── cli.mjs
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   ├── android
│   │   │   │   ├── en
│   │   │   │   │   └── example.xml
│   │   │   │   ├── es
│   │   │   │   │   └── example.xml
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── csv
│   │   │   │   ├── example.csv
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── demo.spec.ts
│   │   │   ├── ejs
│   │   │   │   ├── en
│   │   │   │   │   └── example.ejs
│   │   │   │   ├── es
│   │   │   │   │   └── example.ejs
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── flutter
│   │   │   │   ├── en
│   │   │   │   │   └── example.arb
│   │   │   │   ├── es
│   │   │   │   │   └── example.arb
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── html
│   │   │   │   ├── en
│   │   │   │   │   └── example.html
│   │   │   │   ├── es
│   │   │   │   │   └── example.html
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── json
│   │   │   │   ├── en
│   │   │   │   │   └── example.json
│   │   │   │   ├── es
│   │   │   │   │   └── example.json
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── json-dictionary
│   │   │   │   ├── example.json
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── json5
│   │   │   │   ├── en
│   │   │   │   │   └── example.json5
│   │   │   │   ├── es
│   │   │   │   │   └── example.json5
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── jsonc
│   │   │   │   ├── en
│   │   │   │   │   └── example.jsonc
│   │   │   │   ├── es
│   │   │   │   │   └── example.jsonc
│   │   │   │   ├── i18n.json
│   │   │   │   ├── i18n.lock
│   │   │   │   └── ru
│   │   │   │       └── example.jsonc
│   │   │   ├── markdoc
│   │   │   │   ├── en
│   │   │   │   │   └── example.markdoc
│   │   │   │   ├── es
│   │   │   │   │   └── example.markdoc
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── markdown
│   │   │   │   ├── en
│   │   │   │   │   └── example.md
│   │   │   │   ├── es
│   │   │   │   │   └── example.md
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── mdx
│   │   │   │   ├── en
│   │   │   │   │   └── example.mdx
│   │   │   │   ├── es
│   │   │   │   │   └── example.mdx
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── php
│   │   │   │   ├── en
│   │   │   │   │   └── example.php
│   │   │   │   ├── es
│   │   │   │   │   └── example.php
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── po
│   │   │   │   ├── en
│   │   │   │   │   └── example.po
│   │   │   │   ├── es
│   │   │   │   │   └── example.po
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── properties
│   │   │   │   ├── en
│   │   │   │   │   └── example.properties
│   │   │   │   ├── es
│   │   │   │   │   └── example.properties
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── run_i18n.sh
│   │   │   ├── srt
│   │   │   │   ├── en
│   │   │   │   │   └── example.srt
│   │   │   │   ├── es
│   │   │   │   │   └── example.srt
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── txt
│   │   │   │   ├── en
│   │   │   │   │   └── example.txt
│   │   │   │   ├── es
│   │   │   │   │   └── example.txt
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── typescript
│   │   │   │   ├── en
│   │   │   │   │   └── example.ts
│   │   │   │   ├── es
│   │   │   │   │   └── example.ts
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── vtt
│   │   │   │   ├── en
│   │   │   │   │   └── example.vtt
│   │   │   │   ├── es
│   │   │   │   │   └── example.vtt
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── vue-json
│   │   │   │   ├── example.vue
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── xcode-strings
│   │   │   │   ├── en
│   │   │   │   │   └── example.strings
│   │   │   │   ├── es
│   │   │   │   │   └── example.strings
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── xcode-stringsdict
│   │   │   │   ├── en
│   │   │   │   │   └── example.stringsdict
│   │   │   │   ├── es
│   │   │   │   │   └── example.stringsdict
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── xcode-xcstrings
│   │   │   │   ├── example.xcstrings
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── xcode-xcstrings-v2
│   │   │   │   ├── complex-example.xcstrings
│   │   │   │   ├── example.xcstrings
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── xliff
│   │   │   │   ├── en
│   │   │   │   │   ├── example-v1.2.xliff
│   │   │   │   │   └── example-v2.xliff
│   │   │   │   ├── es
│   │   │   │   │   ├── example-v1.2.xliff
│   │   │   │   │   ├── example-v2.xliff
│   │   │   │   │   └── example.xliff
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── xml
│   │   │   │   ├── en
│   │   │   │   │   └── example.xml
│   │   │   │   ├── es
│   │   │   │   │   └── example.xml
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   ├── yaml
│   │   │   │   ├── en
│   │   │   │   │   └── example.yml
│   │   │   │   ├── es
│   │   │   │   │   └── example.yml
│   │   │   │   ├── i18n.json
│   │   │   │   └── i18n.lock
│   │   │   └── yaml-root-key
│   │   │       ├── en
│   │   │       │   └── example.yml
│   │   │       ├── es
│   │   │       │   └── example.yml
│   │   │       ├── i18n.json
│   │   │       └── i18n.lock
│   │   ├── i18n.json
│   │   ├── i18n.lock
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── cli
│   │   │   │   ├── cmd
│   │   │   │   │   ├── auth.ts
│   │   │   │   │   ├── ci
│   │   │   │   │   │   ├── flows
│   │   │   │   │   │   │   ├── _base.ts
│   │   │   │   │   │   │   ├── in-branch.ts
│   │   │   │   │   │   │   └── pull-request.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── platforms
│   │   │   │   │   │       ├── _base.ts
│   │   │   │   │   │       ├── bitbucket.ts
│   │   │   │   │   │       ├── github.ts
│   │   │   │   │   │       ├── gitlab.ts
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── cleanup.ts
│   │   │   │   │   ├── config
│   │   │   │   │   │   ├── get.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── set.ts
│   │   │   │   │   │   └── unset.ts
│   │   │   │   │   ├── i18n.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── lockfile.ts
│   │   │   │   │   ├── login.ts
│   │   │   │   │   ├── logout.ts
│   │   │   │   │   ├── may-the-fourth.ts
│   │   │   │   │   ├── mcp.ts
│   │   │   │   │   ├── purge.ts
│   │   │   │   │   ├── run
│   │   │   │   │   │   ├── _const.ts
│   │   │   │   │   │   ├── _types.ts
│   │   │   │   │   │   ├── _utils.ts
│   │   │   │   │   │   ├── execute.spec.ts
│   │   │   │   │   │   ├── execute.ts
│   │   │   │   │   │   ├── frozen.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── plan.ts
│   │   │   │   │   │   ├── setup.ts
│   │   │   │   │   │   └── watch.ts
│   │   │   │   │   ├── show
│   │   │   │   │   │   ├── _shared-key-command.ts
│   │   │   │   │   │   ├── config.ts
│   │   │   │   │   │   ├── files.ts
│   │   │   │   │   │   ├── ignored-keys.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── locale.ts
│   │   │   │   │   │   └── locked-keys.ts
│   │   │   │   │   └── status.ts
│   │   │   │   ├── constants.ts
│   │   │   │   ├── index.spec.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── loaders
│   │   │   │   │   ├── _types.ts
│   │   │   │   │   ├── _utils.ts
│   │   │   │   │   ├── android.spec.ts
│   │   │   │   │   ├── android.ts
│   │   │   │   │   ├── csv.spec.ts
│   │   │   │   │   ├── csv.ts
│   │   │   │   │   ├── dato
│   │   │   │   │   │   ├── _base.ts
│   │   │   │   │   │   ├── _utils.ts
│   │   │   │   │   │   ├── api.ts
│   │   │   │   │   │   ├── extract.ts
│   │   │   │   │   │   ├── filter.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── ejs.spec.ts
│   │   │   │   │   ├── ejs.ts
│   │   │   │   │   ├── ensure-key-order.spec.ts
│   │   │   │   │   ├── ensure-key-order.ts
│   │   │   │   │   ├── flat.spec.ts
│   │   │   │   │   ├── flat.ts
│   │   │   │   │   ├── flutter.spec.ts
│   │   │   │   │   ├── flutter.ts
│   │   │   │   │   ├── formatters
│   │   │   │   │   │   ├── _base.ts
│   │   │   │   │   │   ├── biome.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── prettier.ts
│   │   │   │   │   ├── html.ts
│   │   │   │   │   ├── icu-safety.spec.ts
│   │   │   │   │   ├── ignored-keys-buckets.spec.ts
│   │   │   │   │   ├── ignored-keys.spec.ts
│   │   │   │   │   ├── ignored-keys.ts
│   │   │   │   │   ├── index.spec.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── inject-locale.spec.ts
│   │   │   │   │   ├── inject-locale.ts
│   │   │   │   │   ├── json-dictionary.spec.ts
│   │   │   │   │   ├── json-dictionary.ts
│   │   │   │   │   ├── json-sorting.test.ts
│   │   │   │   │   ├── json-sorting.ts
│   │   │   │   │   ├── json.ts
│   │   │   │   │   ├── json5.spec.ts
│   │   │   │   │   ├── json5.ts
│   │   │   │   │   ├── jsonc.spec.ts
│   │   │   │   │   ├── jsonc.ts
│   │   │   │   │   ├── locked-keys.spec.ts
│   │   │   │   │   ├── locked-keys.ts
│   │   │   │   │   ├── locked-patterns.spec.ts
│   │   │   │   │   ├── locked-patterns.ts
│   │   │   │   │   ├── markdoc.spec.ts
│   │   │   │   │   ├── markdoc.ts
│   │   │   │   │   ├── markdown.ts
│   │   │   │   │   ├── mdx.spec.ts
│   │   │   │   │   ├── mdx.ts
│   │   │   │   │   ├── mdx2
│   │   │   │   │   │   ├── _types.ts
│   │   │   │   │   │   ├── _utils.ts
│   │   │   │   │   │   ├── code-placeholder.spec.ts
│   │   │   │   │   │   ├── code-placeholder.ts
│   │   │   │   │   │   ├── frontmatter-split.spec.ts
│   │   │   │   │   │   ├── frontmatter-split.ts
│   │   │   │   │   │   ├── localizable-document.spec.ts
│   │   │   │   │   │   ├── localizable-document.ts
│   │   │   │   │   │   ├── section-split.spec.ts
│   │   │   │   │   │   ├── section-split.ts
│   │   │   │   │   │   └── sections-split-2.ts
│   │   │   │   │   ├── passthrough.ts
│   │   │   │   │   ├── php.ts
│   │   │   │   │   ├── plutil-json-loader.ts
│   │   │   │   │   ├── po
│   │   │   │   │   │   ├── _types.ts
│   │   │   │   │   │   ├── index.spec.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── properties.ts
│   │   │   │   │   ├── root-key.ts
│   │   │   │   │   ├── srt.ts
│   │   │   │   │   ├── sync.ts
│   │   │   │   │   ├── text-file.ts
│   │   │   │   │   ├── txt.ts
│   │   │   │   │   ├── typescript
│   │   │   │   │   │   ├── cjs-interop.ts
│   │   │   │   │   │   ├── index.spec.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── unlocalizable.spec.ts
│   │   │   │   │   ├── unlocalizable.ts
│   │   │   │   │   ├── variable
│   │   │   │   │   │   ├── index.spec.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── vtt.ts
│   │   │   │   │   ├── vue-json.ts
│   │   │   │   │   ├── xcode-strings
│   │   │   │   │   │   ├── escape.ts
│   │   │   │   │   │   ├── parser.ts
│   │   │   │   │   │   ├── tokenizer.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── xcode-strings.spec.ts
│   │   │   │   │   ├── xcode-strings.ts
│   │   │   │   │   ├── xcode-stringsdict.ts
│   │   │   │   │   ├── xcode-xcstrings-icu.spec.ts
│   │   │   │   │   ├── xcode-xcstrings-icu.ts
│   │   │   │   │   ├── xcode-xcstrings-lock-compatibility.spec.ts
│   │   │   │   │   ├── xcode-xcstrings-v2-loader.ts
│   │   │   │   │   ├── xcode-xcstrings.spec.ts
│   │   │   │   │   ├── xcode-xcstrings.ts
│   │   │   │   │   ├── xliff.spec.ts
│   │   │   │   │   ├── xliff.ts
│   │   │   │   │   ├── xml.ts
│   │   │   │   │   └── yaml.ts
│   │   │   │   ├── localizer
│   │   │   │   │   ├── _types.ts
│   │   │   │   │   ├── explicit.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── lingodotdev.ts
│   │   │   │   ├── processor
│   │   │   │   │   ├── _base.ts
│   │   │   │   │   ├── basic.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── lingo.ts
│   │   │   │   └── utils
│   │   │   │       ├── auth.ts
│   │   │   │       ├── buckets.spec.ts
│   │   │   │       ├── buckets.ts
│   │   │   │       ├── cache.ts
│   │   │   │       ├── cloudflare-status.ts
│   │   │   │       ├── config.ts
│   │   │   │       ├── delta.spec.ts
│   │   │   │       ├── delta.ts
│   │   │   │       ├── ensure-patterns.ts
│   │   │   │       ├── errors.ts
│   │   │   │       ├── exec.spec.ts
│   │   │   │       ├── exec.ts
│   │   │   │       ├── exit-gracefully.spec.ts
│   │   │   │       ├── exit-gracefully.ts
│   │   │   │       ├── exp-backoff.ts
│   │   │   │       ├── find-locale-paths.spec.ts
│   │   │   │       ├── find-locale-paths.ts
│   │   │   │       ├── fs.ts
│   │   │   │       ├── init-ci-cd.ts
│   │   │   │       ├── key-matching.spec.ts
│   │   │   │       ├── key-matching.ts
│   │   │   │       ├── lockfile.ts
│   │   │   │       ├── md5.ts
│   │   │   │       ├── observability.ts
│   │   │   │       ├── plutil-formatter.spec.ts
│   │   │   │       ├── plutil-formatter.ts
│   │   │   │       ├── settings.ts
│   │   │   │       ├── ui.ts
│   │   │   │       └── update-gitignore.ts
│   │   │   ├── compiler
│   │   │   │   └── index.ts
│   │   │   ├── locale-codes
│   │   │   │   └── index.ts
│   │   │   ├── react
│   │   │   │   ├── client.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── react-router.ts
│   │   │   │   └── rsc.ts
│   │   │   ├── sdk
│   │   │   │   └── index.ts
│   │   │   └── spec
│   │   │       └── index.ts
│   │   ├── tests
│   │   │   └── mock-storage.ts
│   │   ├── troubleshooting.md
│   │   ├── tsconfig.json
│   │   ├── tsconfig.test.json
│   │   ├── tsup.config.ts
│   │   ├── types
│   │   │   ├── vtt.d.ts
│   │   │   └── xliff.d.ts
│   │   ├── vitest.config.ts
│   │   └── WATCH_MODE.md
│   ├── compiler
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── _base.ts
│   │   │   ├── _const.ts
│   │   │   ├── _loader-utils.spec.ts
│   │   │   ├── _loader-utils.ts
│   │   │   ├── _utils.spec.ts
│   │   │   ├── _utils.ts
│   │   │   ├── client-dictionary-loader.ts
│   │   │   ├── i18n-directive.spec.ts
│   │   │   ├── i18n-directive.ts
│   │   │   ├── index.spec.ts
│   │   │   ├── index.ts
│   │   │   ├── jsx-attribute-flag.spec.ts
│   │   │   ├── jsx-attribute-flag.ts
│   │   │   ├── jsx-attribute-scope-inject.spec.ts
│   │   │   ├── jsx-attribute-scope-inject.ts
│   │   │   ├── jsx-attribute-scopes-export.spec.ts
│   │   │   ├── jsx-attribute-scopes-export.ts
│   │   │   ├── jsx-attribute.spec.ts
│   │   │   ├── jsx-attribute.ts
│   │   │   ├── jsx-fragment.spec.ts
│   │   │   ├── jsx-fragment.ts
│   │   │   ├── jsx-html-lang.spec.ts
│   │   │   ├── jsx-html-lang.ts
│   │   │   ├── jsx-provider.spec.ts
│   │   │   ├── jsx-provider.ts
│   │   │   ├── jsx-remove-attributes.spec.ts
│   │   │   ├── jsx-remove-attributes.ts
│   │   │   ├── jsx-root-flag.spec.ts
│   │   │   ├── jsx-root-flag.ts
│   │   │   ├── jsx-scope-flag.spec.ts
│   │   │   ├── jsx-scope-flag.ts
│   │   │   ├── jsx-scope-inject.spec.ts
│   │   │   ├── jsx-scope-inject.ts
│   │   │   ├── jsx-scopes-export.spec.ts
│   │   │   ├── jsx-scopes-export.ts
│   │   │   ├── lib
│   │   │   │   └── lcp
│   │   │   │       ├── api
│   │   │   │       │   ├── index.ts
│   │   │   │       │   ├── prompt.spec.ts
│   │   │   │       │   ├── prompt.ts
│   │   │   │       │   ├── provider-details.spec.ts
│   │   │   │       │   ├── provider-details.ts
│   │   │   │       │   ├── shots.ts
│   │   │   │       │   ├── xml2obj.spec.ts
│   │   │   │       │   └── xml2obj.ts
│   │   │   │       ├── api.spec.ts
│   │   │   │       ├── cache.spec.ts
│   │   │   │       ├── cache.ts
│   │   │   │       ├── index.spec.ts
│   │   │   │       ├── index.ts
│   │   │   │       ├── schema.ts
│   │   │   │       ├── server.spec.ts
│   │   │   │       └── server.ts
│   │   │   ├── lingo-turbopack-loader.ts
│   │   │   ├── react-router-dictionary-loader.ts
│   │   │   ├── rsc-dictionary-loader.ts
│   │   │   └── utils
│   │   │       ├── ast-key.spec.ts
│   │   │       ├── ast-key.ts
│   │   │       ├── create-locale-import-map.spec.ts
│   │   │       ├── create-locale-import-map.ts
│   │   │       ├── env.spec.ts
│   │   │       ├── env.ts
│   │   │       ├── hash.spec.ts
│   │   │       ├── hash.ts
│   │   │       ├── index.spec.ts
│   │   │       ├── index.ts
│   │   │       ├── invokations.spec.ts
│   │   │       ├── invokations.ts
│   │   │       ├── jsx-attribute-scope.ts
│   │   │       ├── jsx-attribute.spec.ts
│   │   │       ├── jsx-attribute.ts
│   │   │       ├── jsx-content-whitespace.spec.ts
│   │   │       ├── jsx-content.spec.ts
│   │   │       ├── jsx-content.ts
│   │   │       ├── jsx-element.spec.ts
│   │   │       ├── jsx-element.ts
│   │   │       ├── jsx-expressions.test.ts
│   │   │       ├── jsx-expressions.ts
│   │   │       ├── jsx-functions.spec.ts
│   │   │       ├── jsx-functions.ts
│   │   │       ├── jsx-scope.spec.ts
│   │   │       ├── jsx-scope.ts
│   │   │       ├── jsx-variables.spec.ts
│   │   │       ├── jsx-variables.ts
│   │   │       ├── llm-api-key.ts
│   │   │       ├── llm-api-keys.spec.ts
│   │   │       ├── locales.spec.ts
│   │   │       ├── locales.ts
│   │   │       ├── module-params.spec.ts
│   │   │       ├── module-params.ts
│   │   │       ├── observability.spec.ts
│   │   │       ├── observability.ts
│   │   │       ├── rc.spec.ts
│   │   │       └── rc.ts
│   │   ├── tsconfig.json
│   │   ├── tsup.config.ts
│   │   └── vitest.config.ts
│   ├── locales
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── names
│   │   │   │   ├── index.spec.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── integration.spec.ts
│   │   │   │   └── loader.ts
│   │   │   ├── parser.spec.ts
│   │   │   ├── parser.ts
│   │   │   ├── types.ts
│   │   │   ├── validation.spec.ts
│   │   │   └── validation.ts
│   │   ├── tsconfig.json
│   │   └── tsup.config.ts
│   ├── react
│   │   ├── build.config.ts
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── client
│   │   │   │   ├── attribute-component.spec.tsx
│   │   │   │   ├── attribute-component.tsx
│   │   │   │   ├── component.lingo-component.spec.tsx
│   │   │   │   ├── component.spec.tsx
│   │   │   │   ├── component.tsx
│   │   │   │   ├── context.spec.tsx
│   │   │   │   ├── context.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── loader.spec.ts
│   │   │   │   ├── loader.ts
│   │   │   │   ├── locale-switcher.spec.tsx
│   │   │   │   ├── locale-switcher.tsx
│   │   │   │   ├── locale.spec.ts
│   │   │   │   ├── locale.ts
│   │   │   │   ├── provider.spec.tsx
│   │   │   │   ├── provider.tsx
│   │   │   │   ├── utils.spec.ts
│   │   │   │   └── utils.ts
│   │   │   ├── core
│   │   │   │   ├── attribute-component.spec.tsx
│   │   │   │   ├── attribute-component.tsx
│   │   │   │   ├── component.spec.tsx
│   │   │   │   ├── component.tsx
│   │   │   │   ├── const.ts
│   │   │   │   ├── get-dictionary.spec.ts
│   │   │   │   ├── get-dictionary.ts
│   │   │   │   └── index.ts
│   │   │   ├── react-router
│   │   │   │   ├── index.ts
│   │   │   │   ├── loader.spec.ts
│   │   │   │   └── loader.ts
│   │   │   ├── rsc
│   │   │   │   ├── attribute-component.tsx
│   │   │   │   ├── component.lingo-component.spec.tsx
│   │   │   │   ├── component.spec.tsx
│   │   │   │   ├── component.tsx
│   │   │   │   ├── index.ts
│   │   │   │   ├── loader.spec.ts
│   │   │   │   ├── loader.ts
│   │   │   │   ├── provider.spec.tsx
│   │   │   │   ├── provider.tsx
│   │   │   │   ├── utils.spec.ts
│   │   │   │   └── utils.ts
│   │   │   └── test
│   │   │       └── setup.ts
│   │   ├── tsconfig.json
│   │   └── vitest.config.ts
│   ├── sdk
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── abort-controller.specs.ts
│   │   │   ├── index.spec.ts
│   │   │   └── index.ts
│   │   ├── tsconfig.json
│   │   ├── tsconfig.test.json
│   │   └── tsup.config.ts
│   └── spec
│       ├── CHANGELOG.md
│       ├── package.json
│       ├── README.md
│       ├── src
│       │   ├── config.spec.ts
│       │   ├── config.ts
│       │   ├── formats.ts
│       │   ├── index.spec.ts
│       │   ├── index.ts
│       │   ├── json-schema.ts
│       │   ├── locales.spec.ts
│       │   └── locales.ts
│       ├── tsconfig.json
│       ├── tsconfig.test.json
│       └── tsup.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── readme
│   ├── ar.md
│   ├── bn.md
│   ├── de.md
│   ├── en.md
│   ├── es.md
│   ├── fa.md
│   ├── fr.md
│   ├── he.md
│   ├── hi.md
│   ├── it.md
│   ├── ja.md
│   ├── ko.md
│   ├── pl.md
│   ├── pt-BR.md
│   ├── ru.md
│   ├── tr.md
│   ├── uk-UA.md
│   └── zh-Hans.md
├── readme.md
├── scripts
│   ├── docs
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── generate-cli-docs.ts
│   │   │   ├── generate-config-docs.ts
│   │   │   ├── json-schema
│   │   │   │   ├── markdown-renderer.test.ts
│   │   │   │   ├── markdown-renderer.ts
│   │   │   │   ├── parser.test.ts
│   │   │   │   ├── parser.ts
│   │   │   │   └── types.ts
│   │   │   ├── utils.test.ts
│   │   │   └── utils.ts
│   │   ├── tsconfig.json
│   │   └── vitest.config.ts
│   └── packagist-publish.php
└── turbo.json
```

# Files

--------------------------------------------------------------------------------
/packages/cli/src/cli/loaders/html.ts:
--------------------------------------------------------------------------------

```typescript
import { JSDOM } from "jsdom";
import { ILoader } from "./_types";
import { createLoader } from "./_utils";

function normalizeTextContent(text: string, isStandalone: boolean): string {
  // Remove any leading/trailing whitespace for initial comparison
  const trimmed = text.trim();
  if (!trimmed) return "";

  // For all text nodes, just return the trimmed content
  return trimmed;
}

export default function createHtmlLoader(): ILoader<
  string,
  Record<string, any>
> {
  const LOCALIZABLE_ATTRIBUTES: Record<string, string[]> = {
    meta: ["content"],
    img: ["alt"],
    input: ["placeholder"],
    a: ["title"],
  };
  const UNLOCALIZABLE_TAGS = ["script", "style"];

  return createLoader({
    async pull(locale, input) {
      const result: Record<string, any> = {};
      const dom = new JSDOM(input);
      const document = dom.window.document;

      const getPath = (node: Node, attribute?: string): string => {
        const indices: number[] = [];
        let current = node as ChildNode;
        let rootParent = "";

        while (current) {
          const parent = current.parentElement as Element;
          if (!parent) break;

          if (parent === document.documentElement) {
            rootParent = current.nodeName.toLowerCase();
            break;
          }

          // Get index among significant siblings (non-empty text nodes and elements)
          const siblings = Array.from(parent.childNodes).filter(
            (n) =>
              n.nodeType === 1 || (n.nodeType === 3 && n.textContent?.trim()),
          );
          const index = siblings.indexOf(current);
          if (index !== -1) {
            indices.unshift(index);
          }
          current = parent;
        }

        const basePath = rootParent
          ? `${rootParent}/${indices.join("/")}`
          : indices.join("/");
        return attribute ? `${basePath}#${attribute}` : basePath;
      };

      const processNode = (node: Node) => {
        // Check if node is inside an unlocalizable tag
        let parent = node.parentElement;
        while (parent) {
          if (UNLOCALIZABLE_TAGS.includes(parent.tagName.toLowerCase())) {
            return; // Skip processing this node and its children
          }
          parent = parent.parentElement;
        }

        if (node.nodeType === 3) {
          // Text node
          const text = node.textContent || "";
          const normalizedText = normalizeTextContent(text, true);
          if (normalizedText) {
            result[getPath(node)] = normalizedText;
          }
        } else if (node.nodeType === 1) {
          // Element node
          const element = node as Element;

          // Handle localizable attributes
          const tagName = element.tagName.toLowerCase();
          const attributes = LOCALIZABLE_ATTRIBUTES[tagName] || [];
          attributes.forEach((attr) => {
            const value = element.getAttribute(attr);
            if (value) {
              result[getPath(element, attr)] = value;
            }
          });

          // Process all child nodes
          Array.from(element.childNodes)
            .filter(
              (n) =>
                n.nodeType === 1 || (n.nodeType === 3 && n.textContent?.trim()),
            )
            .forEach(processNode);
        }
      };

      // Process head and body
      Array.from(document.head.childNodes)
        .filter(
          (n) =>
            n.nodeType === 1 || (n.nodeType === 3 && n.textContent?.trim()),
        )
        .forEach(processNode);
      Array.from(document.body.childNodes)
        .filter(
          (n) =>
            n.nodeType === 1 || (n.nodeType === 3 && n.textContent?.trim()),
        )
        .forEach(processNode);

      return result;
    },

    async push(locale, data, originalInput) {
      const dom = new JSDOM(
        originalInput ??
          "<!DOCTYPE html><html><head></head><body></body></html>",
      );
      const document = dom.window.document;

      // Set the HTML lang attribute to the current locale
      const htmlElement = document.documentElement;
      htmlElement.setAttribute("lang", locale);

      // Sort paths to ensure proper order of creation
      const paths = Object.keys(data).sort((a, b) => {
        const aDepth = a.split("/").length;
        const bDepth = b.split("/").length;
        return aDepth - bDepth;
      });

      paths.forEach((path) => {
        const value = data[path];
        const [nodePath, attribute] = path.split("#");
        const [rootTag, ...indices] = nodePath.split("/");

        let parent: Element =
          rootTag === "head" ? document.head : document.body;
        let current: Node | null = parent;

        // Navigate to the target node
        for (let i = 0; i < indices.length; i++) {
          const index = parseInt(indices[i]);
          const siblings = Array.from(parent.childNodes).filter(
            (n) =>
              n.nodeType === 1 || (n.nodeType === 3 && n.textContent?.trim()),
          );

          if (index >= siblings.length) {
            // Create missing nodes
            if (i === indices.length - 1) {
              // Last index - create text node
              const textNode = document.createTextNode("");
              parent.appendChild(textNode);
              current = textNode;
            } else {
              // Create intermediate element
              const element = document.createElement("div");
              parent.appendChild(element);
              current = element;
              parent = element;
            }
          } else {
            current = siblings[index];
            if (current.nodeType === 1) {
              parent = current as Element;
            }
          }
        }

        // Set content
        if (current) {
          if (attribute) {
            (current as Element).setAttribute(attribute, value);
          } else {
            current.textContent = value;
          }
        }
      });

      // Preserve formatting by using serialize() with pretty print
      return dom.serialize();
    },
  });
}

```

--------------------------------------------------------------------------------
/readme/it.md:
--------------------------------------------------------------------------------

```markdown
<p align="center">
  <a href="https://lingo.dev">
    <img
      src="https://raw.githubusercontent.com/lingodotdev/lingo.dev/main/content/banner.compiler.png"
      width="100%"
      alt="Lingo.dev"
    />
  </a>
</p>

<p align="center">
  <strong>
    ⚡ Lingo.dev - toolkit open-source per l'i18n, potenziato dall'IA per la
    localizzazione istantanea con LLM.
  </strong>
</p>

<br />

<p align="center">
  <a href="https://lingo.dev/compiler">Lingo.dev Compiler</a> •
  <a href="https://lingo.dev/cli">Lingo.dev CLI</a> •
  <a href="https://lingo.dev/ci">Lingo.dev CI/CD</a> •
  <a href="https://lingo.dev/sdk">Lingo.dev SDK</a>
</p>

<p align="center">
  <a href="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml">
    <img
      src="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml/badge.svg"
      alt="Release"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/blob/main/LICENSE.md">
    <img
      src="https://img.shields.io/github/license/lingodotdev/lingo.dev"
      alt="Licenza"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/commits/main">
    <img
      src="https://img.shields.io/github/last-commit/lingodotdev/lingo.dev"
      alt="Ultimo commit"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-orange?logo=producthunt&style=flat-square"
      alt="Prodotto del giorno #1 su Product Hunt"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/GitHub-Trending-blue?logo=github&style=flat-square"
      alt="Trending su Github"
    />
  </a>
</p>

---

## Scopri il Compiler 🆕

**Lingo.dev Compiler** è un middleware compiler gratuito e open-source, progettato per rendere qualsiasi applicazione React multilingue in fase di compilazione senza richiedere modifiche ai componenti React esistenti.

Installa una volta:

```bash
npm install lingo.dev
```

Abilita nella configurazione di build:

```js
import lingoCompiler from "lingo.dev/compiler";

const existingNextConfig = {};

export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "fr"],
})(existingNextConfig);
```

Esegui `next build` e guarda apparire i bundle in spagnolo e francese ✨

[Leggi la documentazione →](https://lingo.dev/compiler) per la guida completa, e [Unisciti al nostro Discord](https://lingo.dev/go/discord) per ricevere assistenza con la tua configurazione.

---

### Cosa contiene questo repository?

| Strumento    | In breve                                                                              | Documentazione                          |
| ------------ | ------------------------------------------------------------------------------------- | --------------------------------------- |
| **Compiler** | Localizzazione React in fase di build                                                 | [/compiler](https://lingo.dev/compiler) |
| **CLI**      | Localizzazione con un solo comando per app web e mobile, JSON, YAML, markdown e altro | [/cli](https://lingo.dev/cli)           |
| **CI/CD**    | Auto-commit delle traduzioni ad ogni push + creazione di pull request se necessario   | [/ci](https://lingo.dev/ci)             |
| **SDK**      | Traduzione in tempo reale per contenuti generati dagli utenti                         | [/sdk](https://lingo.dev/sdk)           |

Di seguito i punti salienti per ciascuno 👇

---

### ⚡️ Lingo.dev CLI

Traduci codice e contenuti direttamente dal tuo terminale.

```bash
npx lingo.dev@latest run
```

Crea un'impronta digitale per ogni stringa, memorizza i risultati nella cache e ritraduce solo ciò che è cambiato.

[Segui la documentazione →](https://lingo.dev/cli) per imparare come configurarlo.

---

### 🔄 Lingo.dev CI/CD

Distribuisci traduzioni perfette automaticamente.

```yaml
# .github/workflows/i18n.yml
name: Lingo.dev i18n
on: [push]

jobs:
  i18n:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
```

Mantiene il tuo repository aggiornato e il tuo prodotto multilingue senza passaggi manuali.

[Leggi la documentazione →](https://lingo.dev/ci)

---

### 🧩 Lingo.dev SDK

Traduzione istantanea per richiesta per contenuti dinamici.

```ts
import { LingoDotDevEngine } from "lingo.dev/sdk";

const lingoDotDev = new LingoDotDevEngine({
  apiKey: "your-api-key-here",
});

const content = {
  greeting: "Hello",
  farewell: "Goodbye",
  message: "Welcome to our platform",
};

const translated = await lingoDotDev.localizeObject(content, {
  sourceLocale: "en",
  targetLocale: "es",
});
// Returns: { greeting: "Hola", farewell: "Adiós", message: "Bienvenido a nuestra plataforma" }
```

Perfetto per chat, commenti degli utenti e altri flussi in tempo reale.

[Leggi la documentazione →](https://lingo.dev/sdk)

---

## 🤝 Community

Siamo guidati dalla community e amiamo i contributi!

- Hai un'idea? [Apri una issue](https://github.com/lingodotdev/lingo.dev/issues)
- Vuoi correggere qualcosa? [Invia una PR](https://github.com/lingodotdev/lingo.dev/pulls)
- Hai bisogno di aiuto? [Unisciti al nostro Discord](https://lingo.dev/go/discord)

## ⭐ Cronologia delle stelle

Se ti piace quello che stiamo facendo, dacci una ⭐ e aiutaci a raggiungere 4.000 stelle! 🌟

[

![Grafico cronologia stelle](https://api.star-history.com/svg?repos=lingodotdev/lingo.dev&type=Date)

](https://www.star-history.com/#lingodotdev/lingo.dev&Date)

## 🌐 Readme in altre lingue

[English](https://github.com/lingodotdev/lingo.dev) • [中文](/readme/zh-Hans.md) • [日本語](/readme/ja.md) • [한국어](/readme/ko.md) • [Español](/readme/es.md) • [Français](/readme/fr.md) • [Русский](/readme/ru.md) • [Українська](/readme/uk-UA.md) • [Deutsch](/readme/de.md) • [Italiano](/readme/it.md) • [العربية](/readme/ar.md) • [עברית](/readme/he.md) • [हिन्दी](/readme/hi.md) • [বাংলা](/readme/bn.md) • [فارسی](/readme/fa.md)

Non vedi la tua lingua? Aggiungila a [`i18n.json`](./i18n.json) e apri una PR!

```

--------------------------------------------------------------------------------
/demo/react-router-app/app/welcome/logo-light.svg:
--------------------------------------------------------------------------------

```
<svg width="1080" height="174" viewBox="0 0 1080 174" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M231.527 86.9999C231.527 94.9642 228.297 102.173 223.067 107.387C217.837 112.606 210.614 115.835 202.634 115.835C194.654 115.835 187.43 119.059 182.206 124.278C176.977 129.498 173.741 136.707 173.741 144.671C173.741 152.635 170.51 159.844 165.281 165.058C160.051 170.277 152.828 173.507 144.847 173.507C136.867 173.507 129.644 170.277 124.42 165.058C119.19 159.844 115.954 152.635 115.954 144.671C115.954 136.707 119.19 129.498 124.42 124.278C129.644 119.059 136.867 115.835 144.847 115.835C152.828 115.835 160.051 112.606 165.281 107.387C170.51 102.173 173.741 94.9642 173.741 86.9999C173.741 71.0711 160.808 58.1643 144.847 58.1643C136.867 58.1643 129.644 54.9347 124.42 49.7155C119.19 44.502 115.954 37.2931 115.954 29.3287C115.954 21.3643 119.19 14.1555 124.42 8.93622C129.644 3.71698 136.867 0.493164 144.847 0.493164C160.808 0.493164 173.741 13.4 173.741 29.3287C173.741 37.2931 176.977 44.502 182.206 49.7155C187.43 54.9347 194.654 58.1643 202.634 58.1643C218.594 58.1643 231.527 71.0711 231.527 86.9999Z" fill="#F44250"/>
<path d="M115.954 86.9996C115.954 71.0742 103.018 58.1641 87.0608 58.1641C71.1035 58.1641 58.1676 71.0742 58.1676 86.9996C58.1676 102.925 71.1035 115.835 87.0608 115.835C103.018 115.835 115.954 102.925 115.954 86.9996Z" fill="#121212"/>
<path d="M58.1676 144.671C58.1676 128.745 45.2316 115.835 29.2743 115.835C13.317 115.835 0.381104 128.745 0.381104 144.671C0.381104 160.596 13.317 173.506 29.2743 173.506C45.2316 173.506 58.1676 160.596 58.1676 144.671Z" fill="#121212"/>
<path d="M289.313 144.671C289.313 128.745 276.378 115.835 260.42 115.835C244.463 115.835 231.527 128.745 231.527 144.671C231.527 160.596 244.463 173.506 260.42 173.506C276.378 173.506 289.313 160.596 289.313 144.671Z" fill="#121212"/>
<g clip-path="url(#clip0_171_1761)">
<path d="M562.482 173.247C524.388 173.247 498.363 147.49 498.363 110.468C498.363 73.4455 524.388 47.6885 562.482 47.6885C600.576 47.6885 626.869 73.7135 626.869 110.468C626.869 147.222 600.576 173.247 562.482 173.247ZM562.482 144.007C579.386 144.007 587.703 130.319 587.703 110.468C587.703 90.6168 579.386 76.9289 562.482 76.9289C545.579 76.9289 537.529 90.6168 537.529 110.468C537.529 130.319 545.311 144.007 562.482 144.007Z" fill="#121212"/>
<path d="M833.64 141.116C824.217 141.116 819.237 136.684 819.237 126.156V74.8983H851.928V47.7792H819.237V1.15527H791.75L786.1 26.1978C783.343 36.4805 780.82 42.822 773.897 46.0821C773.105 46.4506 771.129 46.9976 769.409 47.3884C768.014 47.701 766.596 47.8573 765.167 47.8573H752.338V47.9243H734.832C723.578 47.9243 714.445 57.0459 714.445 68.3111V111.552C714.445 130.599 707.199 142.668 692.719 142.668C678.238 142.668 672.868 133.279 672.868 116.375V47.9243H634.249V125.765C634.249 151.254 644.442 173.248 676.63 173.248C691.915 173.248 703.895 167.231 711.096 157.182C712.145 155.72 714.445 156.49 714.445 158.276V170.022H753.332V83.8412C753.332 78.8953 757.34 74.8871 762.286 74.8871H779.882V136.952C779.882 164.663 797.89 173.248 817.842 173.248C833.908 173.248 844.436 169.374 853.58 162.441V136.126C846.1 139.453 839.725 141.116 833.629 141.116H833.64Z" fill="#121212"/>
<path d="M981.561 130.865C975.387 157.962 954.197 173.258 923.07 173.258C885.243 173.258 858.415 150.18 858.415 112.354C858.415 74.5281 885.779 47.6992 922.266 47.6992C961.699 47.6992 982.365 74.796 982.365 107.263V113.884H896.509C894.555 135.711 909.382 144.017 924.409 144.017C937.829 144.017 946.136 138.915 950.434 127.918L981.561 130.865ZM945.075 94.9372C944.271 83.1361 936.757 75.8567 921.998 75.8567C906.434 75.8567 899.188 82.321 897.045 94.9372H945.064H945.075Z" fill="#121212"/>
<path d="M1076.24 85.7486C1070.06 82.2652 1064.17 80.9142 1055.85 80.9142C1039.75 80.9142 1029.02 90.0358 1029.02 110.691V170.02H990.393V47.9225H1029.02V64.3235C1029.02 65.4623 1030.54 65.8195 1031.05 64.8035C1036.68 53.5718 1047.91 44.707 1062.03 44.707C1069.27 44.707 1075.45 46.8507 1078.66 49.5414L1076.25 85.7597L1076.24 85.7486Z" fill="#121212"/>
<path d="M547.321 31.5345V23.9983H522.457V31.5345H515.378V2.23828H542.14C553.562 2.23828 554.366 2.95282 554.366 13.1239C554.366 17.4111 553.472 18.5611 551.329 19.6553L549.408 20.6378L551.318 21.6426C553.595 22.8372 554.366 23.2391 554.366 30.0273V31.5345H547.332H547.321ZM522.457 18.3601H547.321V7.88763H522.457V18.349V18.3601Z" fill="#121212"/>
<path d="M578.493 2.23828H610.826V7.90996H580.067V14.5083H610.011V19.2868H580.067V25.8963H610.837V31.501L578.504 31.5345C575.344 31.5345 572.787 28.9778 572.787 25.8293V7.95462C572.787 4.80617 575.344 2.24945 578.493 2.24945V2.23828Z" fill="#121212"/>
<path d="M655.562 31.5345L653.151 26.3429H633.747L631.335 31.5345H624.58L637.007 4.75034C637.71 3.22078 639.262 2.23828 640.937 2.23828H645.927C647.613 2.23828 649.154 3.22078 649.857 4.75034L662.284 31.5345H655.529H655.562ZM643.46 8.06627C642.712 8.06627 642.053 8.49053 641.729 9.17158L635.968 21.5756H650.94L645.19 9.17158C644.878 8.49053 644.208 8.06627 643.46 8.06627Z" fill="#121212"/>
<path d="M694.862 32.4153C676.05 32.4153 675.313 32.4153 675.313 16.8852C675.313 1.35505 676.05 1.36621 694.862 1.36621C711.721 1.36621 713.764 2.06959 714.244 10.5325H707.333V7.01556H682.168V26.766H707.333V23.2714H714.244C713.775 31.7119 711.721 32.4153 694.862 32.4153Z" fill="#121212"/>
<path d="M745.282 31.5345V7.02795H729.16V2.23828H768.148V7.02795H752.026V31.5345H745.282Z" fill="#121212"/>
<path d="M454.419 169.819C450.935 165.264 448.792 154.814 447.452 137.397C446.112 118.104 437.806 113.817 422.532 113.817H392.254V169.83H347.494V0.986328H432.715C476.391 0.986328 498.106 21.6187 498.106 54.5882C498.106 79.2399 482.833 95.3171 462.201 98.0078C479.618 101.491 489.8 111.405 491.676 130.966C494.087 156.154 494.891 163.656 500.518 169.819H454.419ZM424.676 78.704C443.969 78.704 453.615 73.8808 453.615 58.3395C453.615 44.6739 443.969 37.4392 424.676 37.4392H392.254V78.7152H424.676V78.704Z" fill="#121212"/>
</g>
<defs>
<clipPath id="clip0_171_1761">
<rect width="731.156" height="172.261" fill="white" transform="translate(347.494 0.986328)"/>
</clipPath>
</defs>
</svg>

```

--------------------------------------------------------------------------------
/readme/de.md:
--------------------------------------------------------------------------------

```markdown
<p align="center">
  <a href="https://lingo.dev">
    <img
      src="https://raw.githubusercontent.com/lingodotdev/lingo.dev/main/content/banner.compiler.png"
      width="100%"
      alt="Lingo.dev"
    />
  </a>
</p>

<p align="center">
  <strong>
    ⚡ Lingo.dev - Open-Source, KI-gestütztes i18n-Toolkit für sofortige
    Lokalisierung mit LLMs.
  </strong>
</p>

<br />

<p align="center">
  <a href="https://lingo.dev/compiler">Lingo.dev Compiler</a> •
  <a href="https://lingo.dev/cli">Lingo.dev CLI</a> •
  <a href="https://lingo.dev/ci">Lingo.dev CI/CD</a> •
  <a href="https://lingo.dev/sdk">Lingo.dev SDK</a>
</p>

<p align="center">
  <a href="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml">
    <img
      src="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml/badge.svg"
      alt="Release"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/blob/main/LICENSE.md">
    <img
      src="https://img.shields.io/github/license/lingodotdev/lingo.dev"
      alt="Lizenz"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/commits/main">
    <img
      src="https://img.shields.io/github/last-commit/lingodotdev/lingo.dev"
      alt="Letzter Commit"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-orange?logo=producthunt&style=flat-square"
      alt="Product Hunt #1 Produkt des Tages"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/GitHub-Trending-blue?logo=github&style=flat-square"
      alt="Github trending"
    />
  </a>
</p>

---

## Entdecken Sie den Compiler 🆕

**Lingo.dev Compiler** ist eine kostenlose, Open-Source-Compiler-Middleware, die entwickelt wurde, um jede React-Anwendung zur Build-Zeit mehrsprachig zu machen, ohne dass Änderungen an den bestehenden React-Komponenten erforderlich sind.

Einmalige Installation:

```bash
npm install lingo.dev
```

In Ihrer Build-Konfiguration aktivieren:

```js
import lingoCompiler from "lingo.dev/compiler";

const existingNextConfig = {};

export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "fr"],
})(existingNextConfig);
```

Führen Sie `next build` aus und beobachten Sie, wie spanische und französische Bundles erscheinen ✨

[Lesen Sie die Dokumentation →](https://lingo.dev/compiler) für die vollständige Anleitung und [treten Sie unserem Discord bei](https://lingo.dev/go/discord), um Hilfe bei Ihrer Einrichtung zu erhalten.

---

### Was beinhaltet dieses Repository?

| Tool         | Kurzfassung                                                                            | Dokumentation                           |
| ------------ | -------------------------------------------------------------------------------------- | --------------------------------------- |
| **Compiler** | Build-time React-Lokalisierung                                                         | [/compiler](https://lingo.dev/compiler) |
| **CLI**      | Ein-Befehl-Lokalisierung für Web- und Mobile-Apps, JSON, YAML, Markdown + mehr         | [/cli](https://lingo.dev/cli)           |
| **CI/CD**    | Auto-Commit von Übersetzungen bei jedem Push + Erstellung von Pull Requests bei Bedarf | [/ci](https://lingo.dev/ci)             |
| **SDK**      | Echtzeit-Übersetzung für nutzergenerierte Inhalte                                      | [/sdk](https://lingo.dev/sdk)           |

Hier sind die wichtigsten Punkte für jedes Tool 👇

---

### ⚡️ Lingo.dev CLI

Übersetzen Sie Code & Inhalte direkt von Ihrem Terminal aus.

```bash
npx lingo.dev@latest run
```

Es erstellt Fingerabdrücke jedes Strings, speichert Ergebnisse im Cache und übersetzt nur, was sich geändert hat.

[Folgen Sie der Dokumentation →](https://lingo.dev/cli), um zu erfahren, wie Sie es einrichten können.

---

### 🔄 Lingo.dev CI/CD

Liefern Sie automatisch perfekte Übersetzungen.

```yaml
# .github/workflows/i18n.yml
name: Lingo.dev i18n
on: [push]

jobs:
  i18n:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
```

Hält Ihr Repository grün und Ihr Produkt mehrsprachig ohne manuelle Schritte.

[Lesen Sie die Dokumentation →](https://lingo.dev/ci)

---

### 🧩 Lingo.dev SDK

Sofortige Übersetzung pro Anfrage für dynamische Inhalte.

```ts
import { LingoDotDevEngine } from "lingo.dev/sdk";

const lingoDotDev = new LingoDotDevEngine({
  apiKey: "your-api-key-here",
});

const content = {
  greeting: "Hello",
  farewell: "Goodbye",
  message: "Welcome to our platform",
};

const translated = await lingoDotDev.localizeObject(content, {
  sourceLocale: "en",
  targetLocale: "es",
});
// Returns: { greeting: "Hola", farewell: "Adiós", message: "Bienvenido a nuestra plataforma" }
```

Perfekt für Chat, Benutzerkommentare und andere Echtzeit-Workflows.

[Dokumentation lesen →](https://lingo.dev/sdk)

---

## 🤝 Community

Wir sind community-orientiert und schätzen Beiträge!

- Eine Idee? [Issue erstellen](https://github.com/lingodotdev/lingo.dev/issues)
- Möchten Sie etwas verbessern? [PR senden](https://github.com/lingodotdev/lingo.dev/pulls)
- Brauchen Sie Hilfe? [Discord beitreten](https://lingo.dev/go/discord)

## ⭐ Star-Verlauf

Wenn Ihnen gefällt, was wir tun, geben Sie uns einen ⭐ und helfen Sie uns, 4.000 Sterne zu erreichen! 🌟

[

![Star-Verlauf Diagramm](https://api.star-history.com/svg?repos=lingodotdev/lingo.dev&type=Date)

](https://www.star-history.com/#lingodotdev/lingo.dev&Date)

## 🌐 Readme in anderen Sprachen

[English](https://github.com/lingodotdev/lingo.dev) • [中文](/readme/zh-Hans.md) • [日本語](/readme/ja.md) • [한국어](/readme/ko.md) • [Español](/readme/es.md) • [Français](/readme/fr.md) • [Русский](/readme/ru.md) • [Українська](/readme/uk-UA.md) • [Deutsch](/readme/de.md) • [Italiano](/readme/it.md) • [العربية](/readme/ar.md) • [עברית](/readme/he.md) • [हिन्दी](/readme/hi.md) • [বাংলা](/readme/bn.md) • [فارسی](/readme/fa.md)

Ihre Sprache nicht dabei? Fügen Sie sie zu [`i18n.json`](./i18n.json) hinzu und öffnen Sie einen PR!

```

--------------------------------------------------------------------------------
/readme/es.md:
--------------------------------------------------------------------------------

```markdown
<p align="center">
  <a href="https://lingo.dev">
    <img
      src="https://raw.githubusercontent.com/lingodotdev/lingo.dev/main/content/banner.compiler.png"
      width="100%"
      alt="Lingo.dev"
    />
  </a>
</p>

<p align="center">
  <strong>
    ⚡ Lingo.dev - kit de herramientas de i18n de código abierto, potenciado por
    IA para localización instantánea con LLMs.
  </strong>
</p>

<br />

<p align="center">
  <a href="https://lingo.dev/compiler">Lingo.dev Compiler</a> •
  <a href="https://lingo.dev/cli">Lingo.dev CLI</a> •
  <a href="https://lingo.dev/ci">Lingo.dev CI/CD</a> •
  <a href="https://lingo.dev/sdk">Lingo.dev SDK</a>
</p>

<p align="center">
  <a href="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml">
    <img
      src="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml/badge.svg"
      alt="Lanzamiento"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/blob/main/LICENSE.md">
    <img
      src="https://img.shields.io/github/license/lingodotdev/lingo.dev"
      alt="Licencia"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/commits/main">
    <img
      src="https://img.shields.io/github/last-commit/lingodotdev/lingo.dev"
      alt="Último commit"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-orange?logo=producthunt&style=flat-square"
      alt="Producto #1 del día en Product Hunt"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/GitHub-Trending-blue?logo=github&style=flat-square"
      alt="Tendencia en Github"
    />
  </a>
</p>

---

## Conoce el Compiler 🆕

**Lingo.dev Compiler** es un middleware compilador gratuito y de código abierto, diseñado para hacer que cualquier aplicación React sea multilingüe durante el tiempo de compilación sin requerir cambios en los componentes React existentes.

Instalar una vez:

```bash
npm install lingo.dev
```

Habilitar en tu configuración de compilación:

```js
import lingoCompiler from "lingo.dev/compiler";

const existingNextConfig = {};

export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "fr"],
})(existingNextConfig);
```

Ejecuta `next build` y observa cómo aparecen los paquetes en español y francés ✨

[Lee la documentación →](https://lingo.dev/compiler) para la guía completa, y [Únete a nuestro Discord](https://lingo.dev/go/discord) para obtener ayuda con tu configuración.

---

### ¿Qué hay dentro de este repositorio?

| Herramienta  | Resumen                                                                                      | Documentación                           |
| ------------ | -------------------------------------------------------------------------------------------- | --------------------------------------- |
| **Compiler** | Localización de React en tiempo de compilación                                               | [/compiler](https://lingo.dev/compiler) |
| **CLI**      | Localización con un solo comando para aplicaciones web y móviles, JSON, YAML, markdown y más | [/cli](https://lingo.dev/cli)           |
| **CI/CD**    | Auto-commit de traducciones en cada push + creación de pull requests si es necesario         | [/ci](https://lingo.dev/ci)             |
| **SDK**      | Traducción en tiempo real para contenido generado por usuarios                               | [/sdk](https://lingo.dev/sdk)           |

A continuación, los aspectos más destacados de cada uno 👇

---

### ⚡️ Lingo.dev CLI

Traduce código y contenido directamente desde tu terminal.

```bash
npx lingo.dev@latest run
```

Genera huellas digitales de cada cadena, almacena resultados en caché y solo retraduce lo que ha cambiado.

[Sigue la documentación →](https://lingo.dev/cli) para aprender cómo configurarlo.

---

### 🔄 Lingo.dev CI/CD

Entrega traducciones perfectas automáticamente.

```yaml
# .github/workflows/i18n.yml
name: Lingo.dev i18n
on: [push]

jobs:
  i18n:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
```

Mantiene tu repositorio actualizado y tu producto multilingüe sin pasos manuales.

[Lee la documentación →](https://lingo.dev/ci)

---

### 🧩 Lingo.dev SDK

Traducción instantánea por solicitud para contenido dinámico.

```ts
import { LingoDotDevEngine } from "lingo.dev/sdk";

const lingoDotDev = new LingoDotDevEngine({
  apiKey: "your-api-key-here",
});

const content = {
  greeting: "Hello",
  farewell: "Goodbye",
  message: "Welcome to our platform",
};

const translated = await lingoDotDev.localizeObject(content, {
  sourceLocale: "en",
  targetLocale: "es",
});
// Returns: { greeting: "Hola", farewell: "Adiós", message: "Bienvenido a nuestra plataforma" }
```

Perfecto para chat, comentarios de usuarios y otros flujos en tiempo real.

[Leer la documentación →](https://lingo.dev/sdk)

---

## 🤝 Comunidad

Somos impulsados por la comunidad y nos encantan las contribuciones!

- ¿Tienes una idea? [Abre un issue](https://github.com/lingodotdev/lingo.dev/issues)
- ¿Quieres arreglar algo? [Envía un PR](https://github.com/lingodotdev/lingo.dev/pulls)
- ¿Necesitas ayuda? [Únete a nuestro Discord](https://lingo.dev/go/discord)

## ⭐ Historial de estrellas

Si te gusta lo que estamos haciendo, danos una ⭐ y ayúdanos a alcanzar las 4,000 estrellas! 🌟

[

![Gráfico de historial de estrellas](https://api.star-history.com/svg?repos=lingodotdev/lingo.dev&type=Date)

](https://www.star-history.com/#lingodotdev/lingo.dev&Date)

## 🌐 Readme en otros idiomas

[English](https://github.com/lingodotdev/lingo.dev) • [中文](/readme/zh-Hans.md) • [日本語](/readme/ja.md) • [한국어](/readme/ko.md) • [Español](/readme/es.md) • [Français](/readme/fr.md) • [Русский](/readme/ru.md) • [Українська](/readme/uk-UA.md) • [Deutsch](/readme/de.md) • [Italiano](/readme/it.md) • [العربية](/readme/ar.md) • [עברית](/readme/he.md) • [हिन्दी](/readme/hi.md) • [বাংলা](/readme/bn.md) • [فارسی](/readme/fa.md)

¿No ves tu idioma? ¡Agrégalo a [`i18n.json`](./i18n.json) y abre un PR!

```

--------------------------------------------------------------------------------
/readme/fr.md:
--------------------------------------------------------------------------------

```markdown
<p align="center">
  <a href="https://lingo.dev">
    <img
      src="https://raw.githubusercontent.com/lingodotdev/lingo.dev/main/content/banner.compiler.png"
      width="100%"
      alt="Lingo.dev"
    />
  </a>
</p>

<p align="center">
  <strong>
    ⚡ Lingo.dev - boîte à outils i18n open-source, propulsée par l'IA pour une
    localisation instantanée avec les LLMs.
  </strong>
</p>

<br />

<p align="center">
  <a href="https://lingo.dev/compiler">Lingo.dev Compiler</a> •
  <a href="https://lingo.dev/cli">Lingo.dev CLI</a> •
  <a href="https://lingo.dev/ci">Lingo.dev CI/CD</a> •
  <a href="https://lingo.dev/sdk">Lingo.dev SDK</a>
</p>

<p align="center">
  <a href="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml">
    <img
      src="https://github.com/lingodotdev/lingo.dev/actions/workflows/release.yml/badge.svg"
      alt="Publication"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/blob/main/LICENSE.md">
    <img
      src="https://img.shields.io/github/license/lingodotdev/lingo.dev"
      alt="Licence"
    />
  </a>
  <a href="https://github.com/lingodotdev/lingo.dev/commits/main">
    <img
      src="https://img.shields.io/github/last-commit/lingodotdev/lingo.dev"
      alt="Dernier commit"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/Product%20Hunt-%231%20Product%20of%20the%20Day-orange?logo=producthunt&style=flat-square"
      alt="Product Hunt #1 Produit du jour"
    />
  </a>
  <a href="https://lingo.dev/en">
    <img
      src="https://img.shields.io/badge/GitHub-Trending-blue?logo=github&style=flat-square"
      alt="Tendance GitHub"
    />
  </a>
</p>

---

## Découvrez le Compiler 🆕

**Lingo.dev Compiler** est un middleware de compilation gratuit et open-source, conçu pour rendre n'importe quelle application React multilingue au moment de la compilation sans nécessiter de modifications des composants React existants.

Installez une seule fois :

```bash
npm install lingo.dev
```

Activez dans votre configuration de build :

```js
import lingoCompiler from "lingo.dev/compiler";

const existingNextConfig = {};

export default lingoCompiler.next({
  sourceLocale: "en",
  targetLocales: ["es", "fr"],
})(existingNextConfig);
```

Exécutez `next build` et regardez les bundles espagnols et français apparaître ✨

[Consultez la documentation →](https://lingo.dev/compiler) pour le guide complet, et [rejoignez notre Discord](https://lingo.dev/go/discord) pour obtenir de l'aide avec votre configuration.

---

### Que contient ce dépôt ?

| Outil        | En bref                                                                                     | Documentation                           |
| ------------ | ------------------------------------------------------------------------------------------- | --------------------------------------- |
| **Compiler** | Localisation React au moment de la compilation                                              | [/compiler](https://lingo.dev/compiler) |
| **CLI**      | Localisation en une commande pour applications web et mobiles, JSON, YAML, markdown, + plus | [/cli](https://lingo.dev/cli)           |
| **CI/CD**    | Auto-commit des traductions à chaque push + création de pull requests si nécessaire         | [/ci](https://lingo.dev/ci)             |
| **SDK**      | Traduction en temps réel pour le contenu généré par les utilisateurs                        | [/sdk](https://lingo.dev/sdk)           |

Voici un aperçu rapide de chacun 👇

---

### ⚡️ Lingo.dev CLI

Traduisez le code et le contenu directement depuis votre terminal.

```bash
npx lingo.dev@latest run
```

Il crée une empreinte digitale pour chaque chaîne, met en cache les résultats et ne retraduit que ce qui a changé.

[Suivez la documentation →](https://lingo.dev/cli) pour apprendre comment le configurer.

---

### 🔄 Lingo.dev CI/CD

Livrez des traductions parfaites automatiquement.

```yaml
# .github/workflows/i18n.yml
name: Lingo.dev i18n
on: [push]

jobs:
  i18n:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
```

Maintient votre dépôt à jour et votre produit multilingue sans étapes manuelles.

[Lisez la documentation →](https://lingo.dev/ci)

---

### 🧩 Lingo.dev SDK

Traduction instantanée par requête pour le contenu dynamique.

```ts
import { LingoDotDevEngine } from "lingo.dev/sdk";

const lingoDotDev = new LingoDotDevEngine({
  apiKey: "your-api-key-here",
});

const content = {
  greeting: "Hello",
  farewell: "Goodbye",
  message: "Welcome to our platform",
};

const translated = await lingoDotDev.localizeObject(content, {
  sourceLocale: "en",
  targetLocale: "es",
});
// Returns: { greeting: "Hola", farewell: "Adiós", message: "Bienvenido a nuestra plataforma" }
```

Parfait pour les discussions, les commentaires d'utilisateurs et autres flux en temps réel.

[Consulter la documentation →](https://lingo.dev/sdk)

---

## 🤝 Communauté

Nous sommes orientés communauté et adorons les contributions !

- Vous avez une idée ? [Ouvrez un ticket](https://github.com/lingodotdev/lingo.dev/issues)
- Vous souhaitez corriger quelque chose ? [Envoyez une PR](https://github.com/lingodotdev/lingo.dev/pulls)
- Besoin d'aide ? [Rejoignez notre Discord](https://lingo.dev/go/discord)

## ⭐ Historique des étoiles

Si vous appréciez ce que nous faisons, donnez-nous une ⭐ et aidez-nous à atteindre 4 000 étoiles ! 🌟

[

![Graphique d'historique des étoiles](https://api.star-history.com/svg?repos=lingodotdev/lingo.dev&type=Date)

](https://www.star-history.com/#lingodotdev/lingo.dev&Date)

## 🌐 Readme dans d'autres langues

[English](https://github.com/lingodotdev/lingo.dev) • [中文](/readme/zh-Hans.md) • [日本語](/readme/ja.md) • [한국어](/readme/ko.md) • [Español](/readme/es.md) • [Français](/readme/fr.md) • [Русский](/readme/ru.md) • [Українська](/readme/uk-UA.md) • [Deutsch](/readme/de.md) • [Italiano](/readme/it.md) • [العربية](/readme/ar.md) • [עברית](/readme/he.md) • [हिन्दी](/readme/hi.md) • [বাংলা](/readme/bn.md) • [فارسی](/readme/fa.md)

Vous ne voyez pas votre langue ? Ajoutez-la à [`i18n.json`](./i18n.json) et ouvrez une PR !

```

--------------------------------------------------------------------------------
/packages/cli/src/cli/utils/settings.ts:
--------------------------------------------------------------------------------

```typescript
import os from "os";
import path from "path";
import _ from "lodash";
import Z from "zod";
import fs from "fs";
import Ini from "ini";

export type CliSettings = Z.infer<typeof SettingsSchema>;

export function getSettings(explicitApiKey: string | undefined): CliSettings {
  const env = _loadEnv();
  const systemFile = _loadSystemFile();
  const defaults = _loadDefaults();

  _legacyEnvVarWarning();

  _envVarsInfo();

  return {
    auth: {
      apiKey:
        explicitApiKey ||
        env.LINGODOTDEV_API_KEY ||
        systemFile.auth?.apiKey ||
        defaults.auth.apiKey,
      apiUrl:
        env.LINGODOTDEV_API_URL ||
        systemFile.auth?.apiUrl ||
        defaults.auth.apiUrl,
      webUrl:
        env.LINGODOTDEV_WEB_URL ||
        systemFile.auth?.webUrl ||
        defaults.auth.webUrl,
    },
    llm: {
      openaiApiKey: env.OPENAI_API_KEY || systemFile.llm?.openaiApiKey,
      anthropicApiKey: env.ANTHROPIC_API_KEY || systemFile.llm?.anthropicApiKey,
      groqApiKey: env.GROQ_API_KEY || systemFile.llm?.groqApiKey,
      googleApiKey: env.GOOGLE_API_KEY || systemFile.llm?.googleApiKey,
      openrouterApiKey:
        env.OPENROUTER_API_KEY || systemFile.llm?.openrouterApiKey,
      mistralApiKey: env.MISTRAL_API_KEY || systemFile.llm?.mistralApiKey,
    },
  };
}

export function saveSettings(settings: CliSettings): void {
  _saveSystemFile(settings);
}

export function loadSystemSettings() {
  return _loadSystemFile();
}

const flattenZodObject = (schema: Z.ZodObject<any>, prefix = ""): string[] => {
  return Object.entries(schema.shape).flatMap(([key, value]) => {
    const newPrefix = prefix ? `${prefix}.${key}` : key;
    if (value instanceof Z.ZodObject) {
      return flattenZodObject(value, newPrefix);
    }
    return [newPrefix];
  });
};

const SettingsSchema = Z.object({
  auth: Z.object({
    apiKey: Z.string(),
    apiUrl: Z.string(),
    webUrl: Z.string(),
  }),
  llm: Z.object({
    openaiApiKey: Z.string().optional(),
    anthropicApiKey: Z.string().optional(),
    groqApiKey: Z.string().optional(),
    googleApiKey: Z.string().optional(),
    openrouterApiKey: Z.string().optional(),
    mistralApiKey: Z.string().optional(),
  }),
});

export const SETTINGS_KEYS = flattenZodObject(
  SettingsSchema,
) as readonly string[];

// Private

function _loadDefaults(): CliSettings {
  return {
    auth: {
      apiKey: "",
      apiUrl: "https://engine.lingo.dev",
      webUrl: "https://lingo.dev",
    },
    llm: {},
  };
}

function _loadEnv() {
  return Z.object({
    LINGODOTDEV_API_KEY: Z.string().optional(),
    LINGODOTDEV_API_URL: Z.string().optional(),
    LINGODOTDEV_WEB_URL: Z.string().optional(),
    OPENAI_API_KEY: Z.string().optional(),
    ANTHROPIC_API_KEY: Z.string().optional(),
    GROQ_API_KEY: Z.string().optional(),
    GOOGLE_API_KEY: Z.string().optional(),
    OPENROUTER_API_KEY: Z.string().optional(),
    MISTRAL_API_KEY: Z.string().optional(),
  })
    .passthrough()
    .parse(process.env);
}

function _loadSystemFile() {
  const settingsFilePath = _getSettingsFilePath();
  const content = fs.existsSync(settingsFilePath)
    ? fs.readFileSync(settingsFilePath, "utf-8")
    : "";
  const data = Ini.parse(content);

  return Z.object({
    auth: Z.object({
      apiKey: Z.string().optional(),
      apiUrl: Z.string().optional(),
      webUrl: Z.string().optional(),
    }).optional(),
    llm: Z.object({
      openaiApiKey: Z.string().optional(),
      anthropicApiKey: Z.string().optional(),
      groqApiKey: Z.string().optional(),
      googleApiKey: Z.string().optional(),
      openrouterApiKey: Z.string().optional(),
      mistralApiKey: Z.string().optional(),
    }).optional(),
  })
    .passthrough()
    .parse(data);
}

function _saveSystemFile(settings: CliSettings) {
  const settingsFilePath = _getSettingsFilePath();
  const content = Ini.stringify(settings);
  fs.writeFileSync(settingsFilePath, content);
}

function _getSettingsFilePath(): string {
  const settingsFile = ".lingodotdevrc";
  const homedir = os.homedir();
  const settingsFilePath = path.join(homedir, settingsFile);
  return settingsFilePath;
}

function _legacyEnvVarWarning() {
  const env = _loadEnv();

  if (env.REPLEXICA_API_KEY && !env.LINGODOTDEV_API_KEY) {
    console.warn(
      "\x1b[33m%s\x1b[0m",
      `
⚠️  WARNING: REPLEXICA_API_KEY env var is deprecated ⚠️
===========================================================

Please use LINGODOTDEV_API_KEY instead.
===========================================================
`,
    );
  }
}

function _envVarsInfo() {
  const env = _loadEnv();
  const systemFile = _loadSystemFile();

  if (env.LINGODOTDEV_API_KEY && systemFile.auth?.apiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using LINGODOTDEV_API_KEY env var instead of credentials from user config`,
    );
  }
  if (env.OPENAI_API_KEY && systemFile.llm?.openaiApiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using OPENAI_API_KEY env var instead of key from user config.`,
    );
  }
  if (env.ANTHROPIC_API_KEY && systemFile.llm?.anthropicApiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using ANTHROPIC_API_KEY env var instead of key from user config`,
    );
  }
  if (env.GROQ_API_KEY && systemFile.llm?.groqApiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using GROQ_API_KEY env var instead of key from user config`,
    );
  }
  if (env.GOOGLE_API_KEY && systemFile.llm?.googleApiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using GOOGLE_API_KEY env var instead of key from user config`,
    );
  }
  if (env.OPENROUTER_API_KEY && systemFile.llm?.openrouterApiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using OPENROUTER_API_KEY env var instead of key from user config`,
    );
  }
  if (env.MISTRAL_API_KEY && systemFile.llm?.mistralApiKey) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using MISTRAL_API_KEY env var instead of key from user config`,
    );
  }
  if (env.LINGODOTDEV_API_URL) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using LINGODOTDEV_API_URL: ${env.LINGODOTDEV_API_URL}`,
    );
  }
  if (env.LINGODOTDEV_WEB_URL) {
    console.info(
      "\x1b[36m%s\x1b[0m",
      `ℹ️  Using LINGODOTDEV_WEB_URL: ${env.LINGODOTDEV_WEB_URL}`,
    );
  }
}

```

--------------------------------------------------------------------------------
/packages/cli/src/cli/utils/errors.ts:
--------------------------------------------------------------------------------

```typescript
export const docLinks = {
  i18nNotFound: "https://lingo.dev/cli",
  bucketNotFound: "https://lingo.dev/cli",
  authError: "https://lingo.dev/cli",
  localeTargetNotFound: "https://lingo.dev/cli",
  lockFiletNotFound: "https://lingo.dev/cli",
  failedReplexicaEngine: "https://lingo.dev/cli",
  placeHolderFailed: "https://lingo.dev/cli",
  translationFailed: "https://lingo.dev/cli",
  connectionFailed: "https://lingo.dev/cli",
  invalidType: "https://lingo.dev/cli",
  invalidPathPattern: "https://lingo.dev/cli",
  androidResouceError: "https://lingo.dev/cli",
  invalidBucketType: "https://lingo.dev/cli",
  invalidStringDict: "https://lingo.dev/cli",
};

type DocLinkKeys = keyof typeof docLinks;

export class CLIError extends Error {
  public readonly docUrl: string;
  public readonly errorType: string = "cli_error";

  constructor({ message, docUrl }: { message: string; docUrl: DocLinkKeys }) {
    super(message);
    this.docUrl = docLinks[docUrl];
    this.message = `${this.message}\n visit: ${this.docUrl}`;
  }
}

export class ConfigError extends CLIError {
  public readonly errorType = "config_error";

  constructor({ message, docUrl }: { message: string; docUrl: DocLinkKeys }) {
    super({ message, docUrl });
    this.name = "ConfigError";
  }
}

export class AuthenticationError extends CLIError {
  public readonly errorType = "auth_error";

  constructor({ message, docUrl }: { message: string; docUrl: DocLinkKeys }) {
    super({ message, docUrl });
    this.name = "AuthenticationError";
  }
}

export class ValidationError extends CLIError {
  public readonly errorType = "validation_error";

  constructor({ message, docUrl }: { message: string; docUrl: DocLinkKeys }) {
    super({ message, docUrl });
    this.name = "ValidationError";
  }
}

export class LocalizationError extends Error {
  public readonly errorType = "locale_error";
  public readonly bucket?: string;
  public readonly sourceLocale?: string;
  public readonly targetLocale?: string;
  public readonly pathPattern?: string;

  constructor(
    message: string,
    context?: {
      bucket?: string;
      sourceLocale?: string;
      targetLocale?: string;
      pathPattern?: string;
    },
  ) {
    super(message);
    this.name = "LocalizationError";
    this.bucket = context?.bucket;
    this.sourceLocale = context?.sourceLocale;
    this.targetLocale = context?.targetLocale;
    this.pathPattern = context?.pathPattern;
  }
}

export class BucketProcessingError extends Error {
  public readonly errorType = "bucket_error";
  public readonly bucket: string;

  constructor(message: string, bucket: string) {
    super(message);
    this.name = "BucketProcessingError";
    this.bucket = bucket;
  }
}

// Type guard functions for robust error detection
export function isConfigError(error: any): error is ConfigError {
  return error instanceof ConfigError || error.errorType === "config_error";
}

export function isAuthenticationError(
  error: any,
): error is AuthenticationError {
  return (
    error instanceof AuthenticationError || error.errorType === "auth_error"
  );
}

export function isValidationError(error: any): error is ValidationError {
  return (
    error instanceof ValidationError || error.errorType === "validation_error"
  );
}

export function isLocalizationError(error: any): error is LocalizationError {
  return (
    error instanceof LocalizationError || error.errorType === "locale_error"
  );
}

export function isBucketProcessingError(
  error: any,
): error is BucketProcessingError {
  return (
    error instanceof BucketProcessingError || error.errorType === "bucket_error"
  );
}

export function getCLIErrorType(error: any): string {
  if (isConfigError(error)) return "config_error";
  if (isAuthenticationError(error)) return "auth_error";
  if (isValidationError(error)) return "validation_error";
  if (isLocalizationError(error)) return "locale_error";
  if (isBucketProcessingError(error)) return "bucket_error";
  if (error instanceof CLIError) return "cli_error";
  return "unknown_error";
}

// Error detail interface for consistent tracking
export interface ErrorDetail {
  type:
    | "bucket_error"
    | "locale_error"
    | "validation_error"
    | "auth_error"
    | "config_error";
  bucket?: string;
  locale?: string;
  pathPattern?: string;
  message: string;
  stack?: string;
}

// Utility to create previous error context for fatal errors
export function createPreviousErrorContext(errorDetails: ErrorDetail[]) {
  if (errorDetails.length === 0) return undefined;

  return {
    count: errorDetails.length,
    types: [...new Set(errorDetails.map((e) => e.type))],
    buckets: [...new Set(errorDetails.map((e) => e.bucket).filter(Boolean))],
  };
}

// Utility to create aggregated error analytics
export function aggregateErrorAnalytics(
  errorDetails: ErrorDetail[],
  buckets: any[],
  targetLocales: string[],
  i18nConfig: any,
) {
  if (errorDetails.length === 0) {
    return {
      errorCount: 0,
      errorTypes: [],
      errorsByBucket: {},
      errorsByType: {},
      firstError: undefined,
      bucketCount: buckets.length,
      localeCount: targetLocales.length,
      i18nConfig: {
        sourceLocale: i18nConfig.locale.source,
        targetLocales: i18nConfig.locale.targets,
        bucketTypes: Object.keys(i18nConfig.buckets),
      },
    };
  }

  const errorsByBucket = errorDetails.reduce(
    (acc, error) => {
      if (error.bucket) {
        acc[error.bucket] = (acc[error.bucket] || 0) + 1;
      }
      return acc;
    },
    {} as Record<string, number>,
  );

  const errorsByType = errorDetails.reduce(
    (acc, error) => {
      acc[error.type] = (acc[error.type] || 0) + 1;
      return acc;
    },
    {} as Record<string, number>,
  );

  return {
    errorCount: errorDetails.length,
    errorTypes: [...new Set(errorDetails.map((e) => e.type))],
    errorsByBucket,
    errorsByType,
    firstError: {
      type: errorDetails[0].type,
      bucket: errorDetails[0].bucket,
      locale: errorDetails[0].locale,
      pathPattern: errorDetails[0].pathPattern,
      message: errorDetails[0].message,
    },
    bucketCount: buckets.length,
    localeCount: targetLocales.length,
    i18nConfig: {
      sourceLocale: i18nConfig.locale.source,
      targetLocales: i18nConfig.locale.targets,
      bucketTypes: Object.keys(i18nConfig.buckets),
    },
  };
}

```

--------------------------------------------------------------------------------
/packages/cli/src/cli/loaders/flat.ts:
--------------------------------------------------------------------------------

```typescript
import { flatten, unflatten } from "flat";
import { ILoader } from "./_types";
import { composeLoaders, createLoader } from "./_utils";
import _ from "lodash";

export const OBJECT_NUMERIC_KEY_PREFIX = "__lingodotdev__obj__";

/**
 * Options for configuring the flat loader behavior
 */
export interface FlatLoaderOptions {
  /**
   * Optional predicate to determine if an object should be preserved (not flattened)
   * Use this to prevent flattening of special objects like ICU plurals
   */
  shouldPreserveObject?: (value: any) => boolean;
}

/**
 * Creates a flat loader that flattens nested objects into dot-notation keys
 *
 * @param options - Configuration options for the loader
 * @param options.shouldPreserveObject - Predicate to identify objects that should not be flattened
 */
export default function createFlatLoader(options?: FlatLoaderOptions) {
  const composedLoader = composeLoaders(
    createDenormalizeLoader(options),
    createNormalizeLoader(),
  );

  return {
    ...composedLoader,
    pullHints: async (input: Record<string, any>) => {
      if (!input || typeof input !== "object") {
        return {};
      }
      return flattenHints(input);
    },
  };
}

type DenormalizeResult = {
  denormalized: Record<string, string>;
  keysMap: Record<string, string>;
};

function createDenormalizeLoader(
  options?: FlatLoaderOptions,
): ILoader<Record<string, any>, DenormalizeResult> {
  return createLoader({
    pull: async (locale, input) => {
      const inputDenormalized = denormalizeObjectKeys(input || {});

      // First pass: extract preserved objects before flattening (if predicate provided)
      const preservedObjects: Record<string, any> = {};
      const nonPreservedInput: Record<string, any> = {};

      for (const [key, value] of Object.entries(inputDenormalized)) {
        if (options?.shouldPreserveObject?.(value)) {
          preservedObjects[key] = value;
        } else {
          nonPreservedInput[key] = value;
        }
      }

      // Flatten only non-preserved objects
      const flattened: Record<string, string> = flatten(nonPreservedInput, {
        delimiter: "/",
        transformKey(key) {
          return encodeURIComponent(String(key));
        },
      });

      // Merge preserved objects back (they stay as objects, not flattened)
      // BUT: encode their keys too!
      const denormalized: Record<string, any> = { ...flattened };

      for (const [key, value] of Object.entries(preservedObjects)) {
        const encodedKey = encodeURIComponent(String(key));
        denormalized[encodedKey] = value;
      }

      const keysMap = buildDenormalizedKeysMap(denormalized);
      return { denormalized, keysMap };
    },
    push: async (locale, { denormalized }) => {
      const normalized = normalizeObjectKeys(denormalized);
      return normalized;
    },
  });
}

function createNormalizeLoader(): ILoader<
  DenormalizeResult,
  Record<string, string>
> {
  return createLoader({
    pull: async (locale, input) => {
      const normalized = normalizeObjectKeys(input.denormalized);
      return normalized;
    },
    push: async (locale, data, originalInput) => {
      const keysMap = originalInput?.keysMap ?? {};
      const input = mapDenormalizedKeys(data, keysMap);
      const denormalized: Record<string, any> = unflatten(input, {
        delimiter: "/",
        transformKey(key) {
          return decodeURIComponent(String(key));
        },
      });
      return { denormalized, keysMap: keysMap || {} };
    },
  });
}

export function buildDenormalizedKeysMap(obj: Record<string, string>) {
  if (!obj) return {};

  return Object.keys(obj).reduce(
    (acc, key) => {
      if (key) {
        const normalizedKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
        acc[normalizedKey] = key;
      }
      return acc;
    },
    {} as Record<string, string>,
  );
}

export function mapDenormalizedKeys(
  obj: Record<string, any>,
  denormalizedKeysMap: Record<string, string>,
) {
  return Object.keys(obj).reduce(
    (acc, key) => {
      const denormalizedKey = denormalizedKeysMap[key] ?? key;
      acc[denormalizedKey] = obj[key];
      return acc;
    },
    {} as Record<string, string>,
  );
}

export function denormalizeObjectKeys(
  obj: Record<string, any>,
): Record<string, any> {
  if (_.isObject(obj) && !_.isArray(obj)) {
    return _.transform(
      obj,
      (result, value, key) => {
        const newKey = !isNaN(Number(key))
          ? `${OBJECT_NUMERIC_KEY_PREFIX}${key}`
          : key;
        result[newKey] =
          _.isObject(value) && !_.isDate(value)
            ? denormalizeObjectKeys(value)
            : value;
      },
      {} as Record<string, any>,
    );
  } else {
    return obj;
  }
}

export function normalizeObjectKeys(
  obj: Record<string, any>,
): Record<string, any> {
  if (_.isObject(obj) && !_.isArray(obj)) {
    return _.transform(
      obj,
      (result, value, key) => {
        const newKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
        result[newKey] =
          _.isObject(value) && !_.isDate(value)
            ? normalizeObjectKeys(value)
            : value;
      },
      {} as Record<string, any>,
    );
  } else {
    return obj;
  }
}

function flattenHints(
  obj: Record<string, any>,
  parentHints: string[] = [],
  parentPath: string = "",
): Record<string, string[]> {
  const result: Record<string, string[]> = {};

  for (const [key, _value] of Object.entries(obj)) {
    if (_.isObject(_value) && !_.isArray(_value)) {
      const value = _value as Record<string, any>;
      const currentHints = [...parentHints];
      const currentPath = parentPath ? `${parentPath}/${key}` : key;

      // Add this level's hint if it exists
      if (value.hint && typeof value.hint === "string") {
        currentHints.push(value.hint);
      }

      // Process nested objects (excluding the hint property)
      const nestedObj = _.omit(value, "hint");

      // If this is a leaf node (no nested objects), add to result
      if (Object.keys(nestedObj).length === 0) {
        if (currentHints.length > 0) {
          result[currentPath] = currentHints;
        }
      } else {
        // Recursively process nested objects
        const nestedComments = flattenHints(
          nestedObj,
          currentHints,
          currentPath,
        );
        Object.assign(result, nestedComments);
      }
    }
  }

  return result;
}

```

--------------------------------------------------------------------------------
/packages/compiler/src/utils/index.ts:
--------------------------------------------------------------------------------

```typescript
import traverse from "@babel/traverse";
import * as t from "@babel/types";
import _ from "lodash";

import { NodePath } from "@babel/traverse";
import { getJsxAttributeValue, setJsxAttributeValue } from "./jsx-attribute";

// "root" is a JSXElement node that is the root of the JSX tree,
// meaning it doesn't have JSXElement nodes among its ancestors.
export function getJsxRoots(node: t.Node) {
  const result: NodePath<t.JSXElement>[] = [];

  // skip traversing the node if it's a root node
  traverse(node, {
    JSXElement(path) {
      result.push(path);
      path.skip();
    },
  });

  return result;
}

export function isGoodJsxText(path: NodePath<t.JSXText>) {
  return path.node.value?.trim() !== "";
}

export function getOrCreateImport(
  ast: t.Node,
  params: {
    exportedName: string;
    moduleName: string[];
  },
): { importedName: string } {
  let importedName = params.exportedName;
  let existingImport = findExistingImport(
    ast,
    params.exportedName,
    params.moduleName,
  );

  if (existingImport) {
    return { importedName: existingImport };
  }

  // Find a unique import name if needed
  importedName = generateUniqueImportName(ast, params.exportedName);

  // Create the import declaration
  createImportDeclaration(
    ast,
    importedName,
    params.exportedName,
    params.moduleName,
  );

  return { importedName };
}

function findExistingImport(
  ast: t.Node,
  exportedName: string,
  moduleName: string[],
): string | null {
  let result: string | null = null;

  traverse(ast, {
    ImportDeclaration(path) {
      if (!moduleName.includes(path.node.source.value)) {
        return;
      }

      // Skip type-only imports as they can't be used at runtime
      if (path.node.importKind === "type") {
        return;
      }

      for (const specifier of path.node.specifiers) {
        if (
          t.isImportSpecifier(specifier) &&
          // Skip type-only specifiers as they can't be used at runtime
          specifier.importKind !== "type" &&
          ((t.isIdentifier(specifier.imported) &&
            specifier.imported.name === exportedName) ||
            (specifier.importKind === "value" &&
              t.isIdentifier(specifier.local) &&
              specifier.local.name === exportedName))
        ) {
          result = specifier.local.name;
          path.stop();
          return;
        }

        // Handle default imports (import React from "react")
        if (t.isImportDefaultSpecifier(specifier)) {
          // For default imports, we can access the exported name via the default import
          // e.g., React.Fragment when we have "import React from 'react'"
          result = `${specifier.local.name}.${exportedName}`;
          path.stop();
          return;
        }

        // Handle namespace imports (import * as React from "react")
        if (t.isImportNamespaceSpecifier(specifier)) {
          // For namespace imports, we can access the exported name via the namespace
          // e.g., React.Fragment when we have "import * as React from 'react'"
          result = `${specifier.local.name}.${exportedName}`;
          path.stop();
          return;
        }
      }
    },
  });

  return result;
}

function generateUniqueImportName(ast: t.Node, baseName: string): string {
  const usedNames = new Set<string>();

  // Collect all identifiers in scope
  traverse(ast, {
    Identifier(path) {
      usedNames.add(path.node.name);
    },
  });

  // If the base name is available, use it
  if (!usedNames.has(baseName)) {
    return baseName;
  }

  // Otherwise, append a number until we find an unused name
  let counter = 1;
  let candidateName = `${baseName}${counter}`;

  while (usedNames.has(candidateName)) {
    counter++;
    candidateName = `${baseName}${counter}`;
  }

  return candidateName;
}

function createImportDeclaration(
  ast: t.Node,
  localName: string,
  exportedName: string,
  moduleName: string[],
): void {
  traverse(ast, {
    Program(path) {
      // Create the import specifier
      const importSpecifier = t.importSpecifier(
        t.identifier(localName),
        t.identifier(exportedName),
      );

      // Check if we already have a non-type import from this module
      const existingImport = path
        .get("body")
        .find(
          (nodePath) =>
            t.isImportDeclaration(nodePath.node) &&
            moduleName.includes(nodePath.node.source.value) &&
            nodePath.node.importKind !== "type",
        );

      if (existingImport && t.isImportDeclaration(existingImport.node)) {
        // Add to existing import declaration
        existingImport.node.specifiers.push(importSpecifier);
      } else {
        // Create a new import declaration
        const importDeclaration = t.importDeclaration(
          [importSpecifier],
          t.stringLiteral(moduleName[0]),
        );

        // Add it at the top of the file, after any existing imports
        const lastImportIndex = findLastImportIndex(path);
        path.node.body.splice(lastImportIndex + 1, 0, importDeclaration);
      }

      path.stop();
    },
  });
}

function findLastImportIndex(programPath: NodePath<t.Program>): number {
  const body = programPath.node.body;

  for (let i = body.length - 1; i >= 0; i--) {
    if (t.isImportDeclaration(body[i])) {
      return i;
    }
  }

  return -1;
}

function _hasFileDirective(ast: t.Node, directiveValue: string): boolean {
  let hasDirective = false;

  traverse(ast, {
    Directive(path) {
      if (path.node.value.value === directiveValue) {
        hasDirective = true;
        path.stop(); // Stop traversal as soon as we find the directive
      }
    },
  });

  return hasDirective;
}

export function hasI18nDirective(ast: t.Node): boolean {
  return _hasFileDirective(ast, "use i18n");
}

export function hasClientDirective(ast: t.Node): boolean {
  return _hasFileDirective(ast, "use client");
}

export function hasServerDirective(ast: t.Node): boolean {
  return _hasFileDirective(ast, "use server");
}

export function getModuleExecutionMode(
  ast: t.Node,
  rscEnabled: boolean,
): "client" | "server" {
  // if rscEnabled is true, then server mode is the default
  // if rscEnabled is false, then client mode is the default
  // default mode is when there is no directive

  if (rscEnabled) {
    if (hasClientDirective(ast)) {
      return "client";
    } else {
      return "server";
    }
  } else {
    return "client";
  }
}

export { getJsxAttributeValue, setJsxAttributeValue };

```

--------------------------------------------------------------------------------
/packages/cli/src/cli/cmd/run/frozen.ts:
--------------------------------------------------------------------------------

```typescript
import chalk from "chalk";
import { Listr } from "listr2";
import _ from "lodash";
import { minimatch } from "minimatch";

import { colors } from "../../constants";
import { CmdRunContext } from "./_types";
import { commonTaskRendererOptions } from "./_const";
import { getBuckets } from "../../utils/buckets";
import createBucketLoader from "../../loaders";
import { createDeltaProcessor } from "../../utils/delta";
import { resolveOverriddenLocale } from "@lingo.dev/_spec";

export default async function frozen(input: CmdRunContext) {
  console.log(chalk.hex(colors.orange)("[Frozen]"));

  // Prepare filtered buckets consistently with the planning step
  let buckets = getBuckets(input.config!);
  if (input.flags.bucket?.length) {
    buckets = buckets.filter((b) => input.flags.bucket!.includes(b.type));
  }

  if (input.flags.file?.length) {
    buckets = buckets
      .map((bucket: any) => {
        const paths = bucket.paths.filter((p: any) =>
          input.flags.file!.some(
            (f) => p.pathPattern.includes(f) || minimatch(p.pathPattern, f),
          ),
        );
        return { ...bucket, paths };
      })
      .filter((bucket: any) => bucket.paths.length > 0);
  }

  const _sourceLocale = input.flags.sourceLocale || input.config!.locale.source;
  const _targetLocales =
    input.flags.targetLocale || input.config!.locale.targets;

  return new Listr<CmdRunContext>(
    [
      {
        title: "Setting up localization cache",
        task: async (_ctx, task) => {
          const checkLockfileProcessor = createDeltaProcessor("");
          const lockfileExists =
            await checkLockfileProcessor.checkIfLockExists();
          if (!lockfileExists) {
            for (const bucket of buckets) {
              for (const bucketPath of bucket.paths) {
                const resolvedSourceLocale = resolveOverriddenLocale(
                  _sourceLocale,
                  bucketPath.delimiter,
                );

                const loader = createBucketLoader(
                  bucket.type,
                  bucketPath.pathPattern,
                  {
                    defaultLocale: resolvedSourceLocale,
                    injectLocale: bucket.injectLocale,
                    formatter: input.config!.formatter,
                  },
                  bucket.lockedKeys,
                  bucket.lockedPatterns,
                  bucket.ignoredKeys,
                );
                loader.setDefaultLocale(resolvedSourceLocale);
                await loader.init();

                const sourceData = await loader.pull(_sourceLocale);

                const delta = createDeltaProcessor(bucketPath.pathPattern);
                const checksums = await delta.createChecksums(sourceData);
                await delta.saveChecksums(checksums);
              }
            }
            task.title = "Localization cache initialized";
          } else {
            task.title = "Localization cache loaded";
          }
        },
      },
      {
        title: "Validating frozen state",
        enabled: () => !!input.flags.frozen,
        task: async (_ctx, task) => {
          for (const bucket of buckets) {
            for (const bucketPath of bucket.paths) {
              const resolvedSourceLocale = resolveOverriddenLocale(
                _sourceLocale,
                bucketPath.delimiter,
              );

              const loader = createBucketLoader(
                bucket.type,
                bucketPath.pathPattern,
                {
                  defaultLocale: resolvedSourceLocale,
                  returnUnlocalizedKeys: true,
                  injectLocale: bucket.injectLocale,
                },
                bucket.lockedKeys,
                bucket.lockedPatterns,
                bucket.ignoredKeys,
              );
              loader.setDefaultLocale(resolvedSourceLocale);
              await loader.init();

              const { unlocalizable: srcUnlocalizable, ...src } =
                await loader.pull(_sourceLocale);

              const delta = createDeltaProcessor(bucketPath.pathPattern);
              const sourceChecksums = await delta.createChecksums(src);
              const savedChecksums = await delta.loadChecksums();

              const updatedSourceData = _.pickBy(
                src,
                (value, key) => sourceChecksums[key] !== savedChecksums[key],
              );
              if (Object.keys(updatedSourceData).length > 0) {
                throw new Error(
                  `Localization data has changed; please update i18n.lock or run without --frozen. Details: Source file has been updated.`,
                );
              }

              for (const _tgt of _targetLocales) {
                const resolvedTargetLocale = resolveOverriddenLocale(
                  _tgt,
                  bucketPath.delimiter,
                );
                const { unlocalizable: tgtUnlocalizable, ...tgt } =
                  await loader.pull(resolvedTargetLocale);

                const missingKeys = _.difference(
                  Object.keys(src),
                  Object.keys(tgt),
                );
                if (missingKeys.length > 0) {
                  throw new Error(
                    `Localization data has changed; please update i18n.lock or run without --frozen. Details: Target file is missing translations.`,
                  );
                }

                const extraKeys = _.difference(
                  Object.keys(tgt),
                  Object.keys(src),
                );
                if (extraKeys.length > 0) {
                  throw new Error(
                    `Localization data has changed; please update i18n.lock or run without --frozen. Details: Target file has extra translations not present in the source file.`,
                  );
                }

                const unlocalizableDataDiff = !_.isEqual(
                  srcUnlocalizable,
                  tgtUnlocalizable,
                );
                if (unlocalizableDataDiff) {
                  throw new Error(
                    `Localization data has changed; please update i18n.lock or run without --frozen. Details: Unlocalizable data (such as booleans, dates, URLs, etc.) do not match.`,
                  );
                }
              }
            }
          }

          task.title = "No lockfile updates required";
        },
      },
    ],
    {
      rendererOptions: commonTaskRendererOptions,
    },
  ).run(input);
}

```

--------------------------------------------------------------------------------
/packages/locales/src/validation.spec.ts:
--------------------------------------------------------------------------------

```typescript
import { describe, it, expect } from "vitest";
import {
  isValidLocale,
  isValidLanguageCode,
  isValidScriptCode,
  isValidRegionCode,
} from "./validation";

describe("isValidLocale", () => {
  it("should validate basic language-region locales with hyphen", () => {
    expect(isValidLocale("en-US")).toBe(true);
    expect(isValidLocale("es-MX")).toBe(true);
    expect(isValidLocale("fr-CA")).toBe(true);
  });

  it("should validate basic language-region locales with underscore", () => {
    expect(isValidLocale("en_US")).toBe(true);
    expect(isValidLocale("es_MX")).toBe(true);
    expect(isValidLocale("fr_CA")).toBe(true);
  });

  it("should validate language-script-region locales", () => {
    expect(isValidLocale("zh-Hans-CN")).toBe(true);
    expect(isValidLocale("zh-Hant-TW")).toBe(true);
    expect(isValidLocale("sr-Cyrl-RS")).toBe(true);
  });

  it("should validate language-only locales", () => {
    expect(isValidLocale("es")).toBe(true);
    expect(isValidLocale("fr")).toBe(true);
    expect(isValidLocale("zh")).toBe(true);
  });

  it("should validate locales with numeric region codes", () => {
    expect(isValidLocale("es-419")).toBe(true); // Latin America
    expect(isValidLocale("en-001")).toBe(true); // World
  });

  it("should reject invalid locale formats", () => {
    expect(isValidLocale("invalid")).toBe(false);
    expect(isValidLocale("en-")).toBe(false);
    expect(isValidLocale("-US")).toBe(false);
    expect(isValidLocale("en-US-")).toBe(false);
  });

  it("should reject locales with invalid language codes", () => {
    expect(isValidLocale("xyz-US")).toBe(false);
    expect(isValidLocale("fake-CN")).toBe(false);
  });

  it("should reject locales with invalid script codes", () => {
    expect(isValidLocale("en-Fake-US")).toBe(false);
    expect(isValidLocale("zh-Invalid-CN")).toBe(false);
  });

  it("should reject locales with invalid region codes", () => {
    expect(isValidLocale("en-US-FAKE")).toBe(false);
    expect(isValidLocale("en-ZZ")).toBe(false);
  });

  it("should handle edge cases", () => {
    expect(isValidLocale("")).toBe(false);
    expect(isValidLocale("   ")).toBe(false);
    expect(isValidLocale(null as any)).toBe(false);
    expect(isValidLocale(undefined as any)).toBe(false);
  });
});

describe("isValidLanguageCode", () => {
  it("should validate common language codes", () => {
    expect(isValidLanguageCode("en")).toBe(true);
    expect(isValidLanguageCode("es")).toBe(true);
    expect(isValidLanguageCode("fr")).toBe(true);
    expect(isValidLanguageCode("zh")).toBe(true);
    expect(isValidLanguageCode("ar")).toBe(true);
    expect(isValidLanguageCode("ja")).toBe(true);
    expect(isValidLanguageCode("ko")).toBe(true);
  });

  it("should validate less common language codes", () => {
    expect(isValidLanguageCode("aa")).toBe(true); // Afar
    expect(isValidLanguageCode("zu")).toBe(true); // Zulu
    expect(isValidLanguageCode("yi")).toBe(true); // Yiddish
  });

  it("should handle case insensitive validation", () => {
    expect(isValidLanguageCode("EN")).toBe(true);
    expect(isValidLanguageCode("Es")).toBe(true);
    expect(isValidLanguageCode("FR")).toBe(true);
  });

  it("should reject invalid language codes", () => {
    expect(isValidLanguageCode("xyz")).toBe(false);
    expect(isValidLanguageCode("fake")).toBe(false);
    expect(isValidLanguageCode("invalid")).toBe(false);
  });

  it("should handle edge cases", () => {
    expect(isValidLanguageCode("")).toBe(false);
    expect(isValidLanguageCode("   ")).toBe(false);
    expect(isValidLanguageCode(null as any)).toBe(false);
    expect(isValidLanguageCode(undefined as any)).toBe(false);
  });
});

describe("isValidScriptCode", () => {
  it("should validate common script codes", () => {
    expect(isValidScriptCode("Hans")).toBe(true); // Simplified Chinese
    expect(isValidScriptCode("Hant")).toBe(true); // Traditional Chinese
    expect(isValidScriptCode("Latn")).toBe(true); // Latin
    expect(isValidScriptCode("Cyrl")).toBe(true); // Cyrillic
    expect(isValidScriptCode("Arab")).toBe(true); // Arabic
    expect(isValidScriptCode("Hira")).toBe(true); // Hiragana
    expect(isValidScriptCode("Kana")).toBe(true); // Katakana
  });

  it("should validate less common script codes", () => {
    expect(isValidScriptCode("Adlm")).toBe(true); // Adlam
    expect(isValidScriptCode("Zzzz")).toBe(true); // Unknown script
    expect(isValidScriptCode("Qaaa")).toBe(true); // Private use
  });

  it("should be case sensitive", () => {
    expect(isValidScriptCode("hans")).toBe(false);
    expect(isValidScriptCode("HANS")).toBe(false);
    expect(isValidScriptCode("Hans")).toBe(true);
  });

  it("should reject invalid script codes", () => {
    expect(isValidScriptCode("Fake")).toBe(false);
    expect(isValidScriptCode("Invalid")).toBe(false);
    expect(isValidScriptCode("XYZ")).toBe(false);
  });

  it("should handle edge cases", () => {
    expect(isValidScriptCode("")).toBe(false);
    expect(isValidScriptCode("   ")).toBe(false);
    expect(isValidScriptCode(null as any)).toBe(false);
    expect(isValidScriptCode(undefined as any)).toBe(false);
  });
});

describe("isValidRegionCode", () => {
  it("should validate common country codes", () => {
    expect(isValidRegionCode("US")).toBe(true);
    expect(isValidRegionCode("CN")).toBe(true);
    expect(isValidRegionCode("GB")).toBe(true);
    expect(isValidRegionCode("DE")).toBe(true);
    expect(isValidRegionCode("FR")).toBe(true);
    expect(isValidRegionCode("JP")).toBe(true);
    expect(isValidRegionCode("KR")).toBe(true);
  });

  it("should validate numeric region codes", () => {
    expect(isValidRegionCode("419")).toBe(true); // Latin America
    expect(isValidRegionCode("001")).toBe(true); // World
    expect(isValidRegionCode("142")).toBe(true); // Asia
    expect(isValidRegionCode("150")).toBe(true); // Europe
  });

  it("should handle case insensitive validation", () => {
    expect(isValidRegionCode("us")).toBe(true);
    expect(isValidRegionCode("cn")).toBe(true);
    expect(isValidRegionCode("gb")).toBe(true);
  });

  it("should reject invalid region codes", () => {
    expect(isValidRegionCode("ZZ")).toBe(false);
    expect(isValidRegionCode("FAKE")).toBe(false);
    expect(isValidRegionCode("INVALID")).toBe(false);
  });

  it("should handle edge cases", () => {
    expect(isValidRegionCode("")).toBe(false);
    expect(isValidRegionCode("   ")).toBe(false);
    expect(isValidRegionCode(null as any)).toBe(false);
    expect(isValidRegionCode(undefined as any)).toBe(false);
  });
});

```

--------------------------------------------------------------------------------
/packages/cli/src/cli/loaders/inject-locale.spec.ts:
--------------------------------------------------------------------------------

```typescript
import { describe, it, expect } from "vitest";
import createInjectLocaleLoader from "./inject-locale";

const locale = "en";
const originalLocale = "en";

describe("createInjectLocaleLoader", () => {
  describe("pull", () => {
    it("should return data unchanged if injectLocaleKeys is not provided", async () => {
      const loader = createInjectLocaleLoader();
      loader.setDefaultLocale(locale);
      const data = { a: 1, b: 2, locale: "en" };
      const result = await loader.pull(locale, data);
      expect(result).toEqual(data);
    });

    it("should omit keys where value matches locale", async () => {
      const loader = createInjectLocaleLoader([
        "lang",
        "meta.locale",
        "obj.locale",
      ]);
      loader.setDefaultLocale(locale);
      const data = {
        lang: "en",
        value: 42,
        meta: { locale: "en", other: 1 },
        obj: { locale: "en" },
      };
      const result = await loader.pull(locale, data);
      expect(result).toEqual({ value: 42, meta: { other: 1 }, obj: {} });
    });

    it("should not omit keys if their value does not match locale", async () => {
      const loader = createInjectLocaleLoader(["lang", "meta.locale"]);
      loader.setDefaultLocale(locale);
      const data = { lang: "fr", value: 42, meta: { locale: "de", other: 1 } };
      const result = await loader.pull(locale, data);
      expect(result).toEqual(data);
    });

    it("should handle empty data object", async () => {
      const loader = createInjectLocaleLoader(["lang"]);
      loader.setDefaultLocale(locale);
      const data = {};
      const result = await loader.pull(locale, data);
      expect(result).toEqual({});
    });

    it("should omit keys matching wildcard pattern where value matches locale", async () => {
      const loader = createInjectLocaleLoader([
        "pages.*.locale",
        "meta/*/lang",
      ]);
      loader.setDefaultLocale(locale);
      const data = {
        pages: {
          foo: { locale: "en", value: 1 },
          bar: { locale: "en", value: 2 },
          baz: { locale: "fr", value: 3 },
        },
        other: 42,
        "meta/a/lang": "en",
        "meta/b/lang": "fr",
        "meta/c/lang": "en",
      };
      const result = await loader.pull(locale, data);
      expect(result).toEqual({
        pages: {
          foo: { value: 1 },
          bar: { value: 2 },
          baz: { locale: "fr", value: 3 },
        },
        other: 42,
        "meta/b/lang": "fr",
      });
    });
  });

  describe("push", () => {
    it("should return data unchanged if injectLocaleKeys is not provided", async () => {
      const loader = createInjectLocaleLoader();
      loader.setDefaultLocale(locale);
      await loader.pull(locale, { a: 1 });
      const data = { a: 2 };
      const result = await loader.push(locale, data);
      expect(result).toEqual(data);
    });

    it("should set injectLocaleKeys to new locale if they matched originalLocale", async () => {
      const loader = createInjectLocaleLoader(["lang", "meta.locale"]);
      loader.setDefaultLocale(originalLocale);
      const originalInput = {
        lang: "en",
        value: 42,
        meta: { locale: "en", other: 1 },
      };
      await loader.pull(originalLocale, originalInput);
      const data = { value: 99, meta: { other: 2 } };
      const result = await loader.push("fr", data);
      expect(result).toEqual({
        lang: "fr",
        value: 99,
        meta: { locale: "fr", other: 2 },
      });
    });

    it("should not change injectLocaleKeys if they do not match originalLocale", async () => {
      const loader = createInjectLocaleLoader([
        "lang",
        "meta.locale",
        "obj.locale",
      ]);
      loader.setDefaultLocale(originalLocale);
      const originalInput = {
        lang: "de",
        value: 42,
        meta: { locale: "es", other: 1 },
        obj: { locale: "fr" },
      };
      await loader.pull(originalLocale, originalInput);
      const data = {
        lang: "de",
        value: 99,
        meta: { locale: "es", other: 2 },
        obj: { locale: "fr" },
      };
      const result = await loader.push("fr", data);
      expect(result).toEqual({
        lang: "de",
        value: 99,
        meta: { locale: "es", other: 2 },
        obj: { locale: "fr" },
      });
    });

    it("should update injectLocaleKeys, does not add extra keys from originalInput", async () => {
      const loader = createInjectLocaleLoader([
        "lang",
        "meta.locale",
        "obj.locale",
      ]);
      loader.setDefaultLocale(originalLocale);
      const originalInput = {
        lang: "en",
        value: 1,
        meta: { locale: "en", other: 1 },
        obj: { locale: "en" },
        extra: 5,
      };
      await loader.pull(originalLocale, originalInput);
      const data = { value: 2, meta: { other: 2 } };
      const result = await loader.push("fr", data);
      expect(result).toEqual({
        lang: "fr",
        value: 2,
        meta: { locale: "fr", other: 2 },
        obj: { locale: "fr" },
      });
    });

    it("should not inject locale if it was not in originalInput", async () => {
      const loader = createInjectLocaleLoader(["lang"]);
      loader.setDefaultLocale(originalLocale);
      const originalInput = { value: 1, meta: { other: 1 } };
      await loader.pull(originalLocale, originalInput);
      const data = { value: 2, meta: { other: 2 } };
    });

    it("should set wildcard-matched keys to new locale if they matched originalLocale", async () => {
      const loader = createInjectLocaleLoader([
        "pages.*.locale",
        "meta/*/lang",
      ]);
      loader.setDefaultLocale(originalLocale);
      const originalInput = {
        pages: {
          foo: { locale: "en", value: 1 },
          bar: { locale: "en", value: 2 },
          baz: { locale: "fr", value: 3 },
        },
        "meta/a/lang": "en",
        "meta/b/lang": "fr",
        "meta/c/lang": "en",
      };
      await loader.pull(originalLocale, originalInput);
      const data = {
        pages: {
          foo: { value: 10 },
          bar: { value: 20 },
          baz: { locale: "fr", value: 30 },
        },
        "meta/b/lang": "fr",
      };
      const result = await loader.push("de", data);
      expect(result).toEqual({
        pages: {
          foo: { locale: "de", value: 10 },
          bar: { locale: "de", value: 20 },
          baz: { locale: "fr", value: 30 },
        },
        "meta/a/lang": "de",
        "meta/b/lang": "fr",
        "meta/c/lang": "de",
      });
    });
  });
});

```

--------------------------------------------------------------------------------
/packages/cli/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "lingo.dev",
  "version": "0.114.4",
  "description": "Lingo.dev CLI",
  "private": false,
  "publishConfig": {
    "access": "public"
  },
  "type": "module",
  "sideEffects": false,
  "exports": {
    "./cli": {
      "types": "./build/cli.d.ts",
      "import": "./build/cli.mjs",
      "require": "./build/cli.cjs"
    },
    "./sdk": {
      "types": "./build/sdk.d.ts",
      "import": "./build/sdk.mjs",
      "require": "./build/sdk.cjs"
    },
    "./spec": {
      "types": "./build/spec.d.ts",
      "import": "./build/spec.mjs",
      "require": "./build/spec.cjs"
    },
    "./compiler": {
      "types": "./build/compiler.d.ts",
      "import": "./build/compiler.mjs",
      "require": "./build/compiler.cjs"
    },
    "./react": {
      "types": "./build/react.d.ts",
      "import": "./build/react.mjs",
      "require": "./build/react.cjs"
    },
    "./react-client": {
      "types": "./build/react/client.d.ts",
      "import": "./build/react/client.mjs",
      "require": "./build/react/client.cjs"
    },
    "./react/client": {
      "types": "./build/react/client.d.ts",
      "import": "./build/react/client.mjs",
      "require": "./build/react/client.cjs"
    },
    "./react-rsc": {
      "types": "./build/react/rsc.d.ts",
      "import": "./build/react/rsc.mjs",
      "require": "./build/react/rsc.cjs"
    },
    "./react/rsc": {
      "types": "./build/react/rsc.d.ts",
      "import": "./build/react/rsc.mjs",
      "require": "./build/react/rsc.cjs"
    },
    "./react-router": {
      "types": "./build/react/react-router.d.ts",
      "import": "./build/react/react-router.mjs",
      "require": "./build/react/react-router.cjs"
    },
    "./react/react-router": {
      "types": "./build/react/react-router.d.ts",
      "import": "./build/react/react-router.mjs",
      "require": "./build/react/react-router.cjs"
    },
    "./locale-codes": {
      "types": "./build/locale-codes.d.ts",
      "import": "./build/locale-codes.mjs",
      "require": "./build/locale-codes.cjs"
    }
  },
  "typesVersions": {
    "*": {
      "sdk": [
        "./build/sdk.d.ts"
      ],
      "cli": [
        "./build/cli.d.ts"
      ],
      "spec": [
        "./build/spec.d.ts"
      ],
      "compiler": [
        "./build/compiler.d.ts"
      ],
      "react": [
        "./build/react.d.ts"
      ],
      "react/client": [
        "./build/react/client.d.ts"
      ],
      "react/rsc": [
        "./build/react/rsc.d.ts"
      ],
      "react/react-router": [
        "./build/react/react-router.d.ts"
      ],
      "locale-codes": [
        "./build/locale-codes.d.ts"
      ]
    }
  },
  "bin": {
    "lingo.dev": "./bin/cli.mjs"
  },
  "files": [
    "bin",
    "build",
    "assets"
  ],
  "scripts": {
    "lingo.dev": "node --inspect=9229 ./bin/cli.mjs",
    "dev": "tsup --watch",
    "build": "pnpm typecheck && tsup",
    "typecheck": "tsc --noEmit",
    "test": "vitest run",
    "test:watch": "vitest",
    "clean": "rm -rf build"
  },
  "keywords": [],
  "author": "",
  "license": "Apache-2.0",
  "dependencies": {
    "@ai-sdk/anthropic": "^1.2.11",
    "@ai-sdk/google": "^1.2.19",
    "@ai-sdk/mistral": "^1.2.8",
    "@ai-sdk/openai": "^1.3.22",
    "@babel/generator": "^7.27.1",
    "@babel/parser": "^7.27.1",
    "@babel/traverse": "^7.27.4",
    "@babel/types": "^7.27.1",
    "@biomejs/js-api": "^3.0.0",
    "@biomejs/wasm-nodejs": "^2.2.4",
    "@datocms/cma-client-node": "^4.0.1",
    "@gitbeaker/rest": "^39.34.3",
    "@inkjs/ui": "^2.0.0",
    "@inquirer/prompts": "^7.8.0",
    "@lingo.dev/_compiler": "workspace:*",
    "@lingo.dev/_locales": "workspace:*",
    "@lingo.dev/_react": "workspace:*",
    "@lingo.dev/_sdk": "workspace:*",
    "@lingo.dev/_spec": "workspace:*",
    "@markdoc/markdoc": "^0.5.4",
    "@modelcontextprotocol/sdk": "^1.5.0",
    "@openrouter/ai-sdk-provider": "^0.7.1",
    "@paralleldrive/cuid2": "^2.2.2",
    "@types/ejs": "^3.1.5",
    "ai": "^4.3.15",
    "bitbucket": "^2.12.0",
    "chalk": "^5.4.1",
    "chokidar": "^4.0.3",
    "cli-progress": "^3.12.0",
    "cli-table3": "^0.6.5",
    "cors": "^2.8.5",
    "csv-parse": "^5.6.0",
    "csv-stringify": "^6.5.2",
    "date-fns": "^4.1.0",
    "dedent": "^1.5.3",
    "diff": "^7.0.0",
    "dotenv": "^16.4.7",
    "ejs": "^3.1.10",
    "express": "^5.1.0",
    "external-editor": "^3.1.0",
    "figlet": "^1.8.2",
    "flat": "^6.0.1",
    "gettext-parser": "^8.0.0",
    "glob": "<11.0.0",
    "gradient-string": "^3.0.0",
    "gray-matter": "^4.0.3",
    "ini": "^5.0.0",
    "ink": "^4.2.0",
    "ink-progress-bar": "^3.0.0",
    "ink-spinner": "^5.0.0",
    "inquirer": "^12.6.0",
    "interactive-commander": "^0.5.194",
    "is-url": "^1.2.4",
    "jsdom": "^25.0.1",
    "json5": "^2.2.3",
    "jsonc-parser": "^3.3.1",
    "jsonrepair": "^3.11.2",
    "listr2": "^8.3.2",
    "lodash": "^4.17.21",
    "marked": "^15.0.6",
    "mdast-util-from-markdown": "^2.0.2",
    "mdast-util-gfm": "^3.1.0",
    "micromark-extension-gfm": "^3.0.0",
    "node-machine-id": "^1.1.12",
    "node-webvtt": "^1.9.4",
    "object-hash": "^3.0.0",
    "octokit": "^4.0.2",
    "ollama-ai-provider": "^1.2.0",
    "open": "^10.2.0",
    "ora": "^8.1.1",
    "p-limit": "^6.2.0",
    "php-array-reader": "^2.1.2",
    "plist": "^3.1.0",
    "posthog-node": "^5.8.1",
    "prettier": "^3.4.2",
    "react": "^18.3.1",
    "rehype-stringify": "^10.0.1",
    "remark-disable-tokenizers": "^1.1.1",
    "remark-frontmatter": "^5.0.0",
    "remark-gfm": "^4.0.1",
    "remark-mdx": "^3.1.0",
    "remark-mdx-frontmatter": "^5.1.0",
    "remark-parse": "^11.0.0",
    "remark-rehype": "^11.1.2",
    "remark-stringify": "^11.0.0",
    "sax": "^1.4.1",
    "srt-parser-2": "^1.2.3",
    "unified": "^11.0.5",
    "unist-util-visit": "^5.0.0",
    "vfile": "^6.0.3",
    "xliff": "^6.2.1",
    "xml2js": "^0.6.2",
    "xpath": "^0.0.34",
    "yaml": "^2.7.0",
    "zod": "^3.25.76"
  },
  "devDependencies": {
    "@types/babel__generator": "^7.27.0",
    "@types/chokidar": "^2.1.7",
    "@types/cli-progress": "^3.11.6",
    "@types/cors": "^2.8.17",
    "@types/diff": "^7.0.0",
    "@types/express": "^5.0.3",
    "@types/figlet": "^1.7.0",
    "@types/gettext-parser": "^4.0.4",
    "@types/glob": "^8.1.0",
    "@types/ini": "^4.1.1",
    "@types/is-url": "^1.2.32",
    "@types/jsdom": "^21.1.7",
    "@types/lodash": "^4.17.16",
    "@types/mdast": "^4.0.4",
    "@types/node": "^22.10.2",
    "@types/node-gettext": "^3.0.6",
    "@types/object-hash": "^3.0.6",
    "@types/plist": "^3.0.5",
    "@types/react": "^18.3.20",
    "@types/xml2js": "^0.4.14",
    "tsup": "^8.3.5",
    "typescript": "^5.8.3",
    "vitest": "^3.1.2"
  },
  "engines": {
    "node": ">=18"
  },
  "packageManager": "[email protected]"
}

```

--------------------------------------------------------------------------------
/demo/react-router-app/app/lingo/meta.json:
--------------------------------------------------------------------------------

```json
{
  "version": 0.1,
  "files": {
    "root.tsx": {
      "scopes": {
        "9/declaration/body/1/argument/1/1/3-content": {
          "type": "attribute",
          "hash": "d94b318cb327f61f1aea44a6cb1fdcad",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "width=device-width, initial-scale=1"
        }
      }
    },
    "routes/test.tsx": {
      "scopes": {
        "3/declaration/body/0/argument/1/1": {
          "type": "element",
          "hash": "a0ac69aec348674378faaf92ce476f64",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "Go back home"
        },
        "3/declaration/body/0/argument/1/3": {
          "type": "element",
          "hash": "51eb13586d30537dfa934742439cc7ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "This is a test page"
        },
        "3/declaration/body/0/argument/1/5": {
          "type": "element",
          "hash": "792a8d0c1ca71a88ab7d887075e69b1d",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "Welcome to non-interactive testing page."
        },
        "3/declaration/body/0/argument/1/7": {
          "type": "element",
          "hash": "31ab29a98c0bb54378cb5a2390d07e57",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "Please do not try to interact with this page for your own safety."
        }
      }
    },
    "welcome/welcome.tsx": {
      "scopes": {
        "3/declaration/body/0/argument/1/1/1/1-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "3/declaration/body/0/argument/1/1/1/3-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "3/declaration/body/0/argument/1/1/3/1-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "3/declaration/body/0/argument/1/1/3/3-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "3/declaration/body/0/argument/1/3": {
          "type": "element",
          "hash": "4938894bf1608cee94696ec86f5d059a",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "Test"
        },
        "3/declaration/body/0/argument/1/5/1/1": {
          "type": "element",
          "hash": "e0d9d29b9e761346e506557eb7b7e798",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "What's next?"
        },
        "4/declaration/body/0/argument/1/1": {
          "type": "element",
          "hash": "201cf15cf0830aaaf478e49a9665d096",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "<element:LingoDotDev></element:LingoDotDev> 💚<element:div><element:img></element:img><element:img></element:img></element:div>"
        },
        "4/declaration/body/0/argument/1/1/3": {
          "type": "element",
          "hash": "0ecc986bbbb51a93878f2d11bb45c04a",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "💚"
        },
        "4/declaration/body/0/argument/1/1/3/1-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/1/3/3-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/1/5/1-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/1/5/1/1-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/1/5/1/3-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/1/5/3-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/1/5/5-alt": {
          "type": "attribute",
          "hash": "68ae50c1603f87d51e788a96b419f2ee",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "React Router"
        },
        "4/declaration/body/0/argument/1/3": {
          "type": "element",
          "hash": "4e5098c50297642cf07ce303398bad59",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "Open test page"
        },
        "4/declaration/body/0/argument/1/5": {
          "type": "element",
          "hash": "a90f2300128bce36346e0debd0b6092b",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "Welcome to your new React Router application! This starter template includes everything you need to get started with React Router and Lingo.dev for internationalization."
        },
        "4/declaration/body/0/argument/1/5/1/1": {
          "type": "element",
          "hash": "e0d9d29b9e761346e506557eb7b7e798",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "What's next?"
        },
        "4/declaration/body/0/argument/1/7/1/1": {
          "type": "element",
          "hash": "e0d9d29b9e761346e506557eb7b7e798",
          "context": "",
          "skip": false,
          "overrides": {},
          "content": "What's next?"
        }
      }
    }
  }
}

```

--------------------------------------------------------------------------------
/demo/vite-project/src/lingo-dot-dev.tsx:
--------------------------------------------------------------------------------

```typescript
import type { SVGProps } from "react";

export function LingoDotDev(props: SVGProps<SVGSVGElement>) {
  const { width, height, ...rest } = props;
  return (
    <svg
      width={width ? width : !height ? 300 : undefined}
      height={height ? height : !width ? 46 : undefined}
      viewBox="0 0 150 26"
      fill="#000000"
      xmlns="http://www.w3.org/2000/svg"
      {...rest}
    >
      <path
        d="M0.0528644 9.3081L9.51858 19.6347C9.55631 19.6754 9.60893 19.6992 9.66454 19.6992H25.1832C25.36 19.6992 25.4483 19.4857 25.3232 19.3606L18.5126 12.5501H13.1508V15.231L6.89523 8.97546H0.198827C0.026055 8.97546 -0.0643027 9.181 0.0528644 9.3081Z"
        fill="#69E300"
      ></path>
      <path
        d="M25.3593 12.2182L15.8926 1.89157C15.8548 1.85086 15.8022 1.82703 15.7466 1.82703H0.227916C0.0501791 1.82703 -0.0381927 2.04051 0.0869179 2.16562L6.8975 8.9762H12.2594V6.29526L18.5149 12.5508H25.2123C25.3851 12.5508 25.4754 12.3453 25.3583 12.2182H25.3593Z"
        fill="#69E300"
      ></path>
      <path d="M104.582 19.7876H101.476V16.7095H104.582V19.7876Z"></path>
      <path d="M109.677 19.1594C108.713 18.5597 107.951 17.7139 107.389 16.6255C106.827 15.537 106.543 14.2995 106.543 12.9199C106.543 11.5402 106.824 10.3097 107.389 9.22814C107.951 8.14662 108.717 7.30775 109.677 6.70807C110.641 6.10838 111.712 5.81027 112.894 5.81027C114.62 5.81027 116 6.46542 117.036 7.77225H117.171V0.711182H119.868V19.7868H117.553L117.279 18.0432H117.143C116.09 19.3882 114.672 20.0607 112.894 20.0607C111.712 20.0607 110.641 19.7626 109.677 19.1629V19.1594ZM115.195 16.979C115.802 16.5977 116.284 16.0535 116.641 15.3429C116.994 14.6357 117.171 13.8246 117.171 12.9164C117.171 12.0082 116.994 11.204 116.641 10.5038C116.287 9.80357 115.805 9.26281 115.195 8.8815C114.585 8.5002 113.927 8.30955 113.22 8.30955C112.512 8.30955 111.829 8.5002 111.23 8.8815C110.63 9.26281 110.152 9.80357 109.798 10.5038C109.445 11.204 109.268 12.0082 109.268 12.9164C109.268 13.8246 109.445 14.6565 109.798 15.3568C110.152 16.057 110.63 16.5977 111.23 16.979C111.829 17.3603 112.492 17.551 113.22 17.551C113.947 17.551 114.585 17.3603 115.195 16.979Z"></path>
      <path d="M126.219 16.6632C127.051 17.2802 127.901 17.7135 128.972 17.7135C129.734 17.7135 130.407 17.5402 130.989 17.197C131.572 16.8504 132.005 16.4067 132.296 15.8625H135.104C134.684 17.0792 133.95 18.0844 132.896 18.8748C131.842 19.6651 130.535 20.0603 128.972 20.0603C127.7 20.0603 126.545 19.7552 125.512 19.1486C124.476 18.542 123.665 17.6962 123.072 16.6147C122.483 15.5332 122.188 14.3026 122.188 12.923C122.188 11.5433 122.483 10.3405 123.072 9.25896C123.661 8.17744 124.476 7.33511 125.512 6.72502C126.549 6.1184 127.7 5.81335 128.972 5.81335C130.244 5.81335 131.291 6.10453 132.282 6.68689C133.274 7.26925 134.053 8.06652 134.625 9.08564C135.197 10.1048 135.485 11.2487 135.485 12.5174C135.485 13.1517 135.44 13.6336 135.35 13.9629H124.874L127.121 11.8934H132.819C132.729 10.805 132.327 9.90371 131.62 9.19657C130.913 8.48942 130.029 8.13238 128.979 8.13238C127.928 8.13238 126.972 8.48595 126.226 9.19657C125.481 9.90371 125.037 10.805 124.892 11.8934C124.892 11.8934 124.316 15.2628 126.226 16.6736L126.219 16.6632Z"></path>
      <path d="M144.556 19.7876H140.605L135.783 6.08142H138.618L142.324 16.7372H142.868L146.574 6.08142H149.409L144.56 19.7876H144.556Z"></path>
      <path d="M53.4117 3.49132H50.4688V0.766724H53.4117V3.49132ZM53.2765 19.7869H50.5797V6.08073H53.2765V19.7869Z"></path>
      <path d="M56.2451 19.7872V6.08105H58.5607L58.8345 7.49881H58.9697C59.3129 7.06204 59.8398 6.6738 60.5504 6.32716C61.2575 5.98052 62.0756 5.81067 63.0046 5.81067C64.0584 5.81067 64.9978 6.05332 65.8263 6.53168C66.6513 7.01351 67.2995 7.68946 67.7605 8.563C68.225 9.43653 68.4538 10.4349 68.4538 11.5614V19.7907H65.7569V11.7798C65.7569 10.7988 65.438 9.98076 64.8037 9.32561C64.1693 8.67045 63.379 8.34461 62.4327 8.34461C61.7983 8.34461 61.2125 8.5006 60.6752 8.80911C60.1379 9.11762 59.7185 9.53706 59.4065 10.064C59.098 10.5908 58.942 11.1628 58.942 11.7798V19.7907H56.2451V19.7872Z"></path>
      <path d="M73.9972 24.772C73.0613 24.2832 72.3472 23.6697 71.8585 22.9313C71.3697 22.193 71.1062 21.4477 71.0681 20.6817H73.7927C73.8655 21.316 74.2121 21.8776 74.8292 22.3559C75.4462 22.8378 76.3024 23.0769 77.3908 23.0769C78.4793 23.0769 79.4152 22.758 80.0877 22.1237C80.7602 21.4859 81.0964 20.6435 81.0964 19.5897V17.4094H80.9612C80.4898 17.9363 79.897 18.3557 79.1899 18.6642C78.4828 18.9727 77.6993 19.1287 76.8466 19.1287C75.6646 19.1287 74.6004 18.8479 73.6436 18.2829C72.6904 17.7213 71.9416 16.931 71.3974 15.9119C70.8532 14.8962 70.5793 13.7419 70.5793 12.4524C70.5793 11.1629 70.8532 10.0121 71.3974 9.00679C71.9416 7.99807 72.6904 7.21466 73.6436 6.64964C74.5969 6.08808 75.6646 5.80383 76.8466 5.80383C77.7201 5.80383 78.5209 5.97715 79.2592 6.32033C79.9941 6.66697 80.5903 7.128 81.0444 7.71036H81.1796L81.4535 6.07421H83.7968V19.6175C83.7968 20.7787 83.5437 21.8048 83.0341 22.6956C82.5246 23.5865 81.7862 24.2763 80.8122 24.7651C79.8416 25.2573 78.7011 25.5 77.3908 25.5C76.0805 25.5 74.9332 25.2538 73.9972 24.7651V24.772ZM79.1726 16.1476C79.7619 15.794 80.2298 15.2949 80.5765 14.6501C80.9231 14.0054 81.093 13.2739 81.093 12.4559C81.093 11.6378 80.9196 10.9133 80.5765 10.2755C80.2298 9.64115 79.7619 9.14545 79.1726 8.79188C78.5833 8.4383 77.9247 8.26152 77.1967 8.26152C76.0701 8.26152 75.1411 8.65322 74.4028 9.43316C73.6679 10.2131 73.3005 11.2218 73.3005 12.4593C73.3005 13.6968 73.6679 14.7298 74.4028 15.5098C75.1377 16.2897 76.0701 16.6814 77.1967 16.6814C77.9247 16.6814 78.5833 16.5046 79.1726 16.1511V16.1476Z"></path>
      <path d="M89.2696 19.1459C88.2331 18.5393 87.422 17.6935 86.8292 16.612C86.24 15.5305 85.9453 14.2999 85.9453 12.9203C85.9453 11.5406 86.24 10.3378 86.8292 9.25628C87.4185 8.17476 88.2331 7.33242 89.2696 6.72233C90.3061 6.11571 91.4569 5.81067 92.7291 5.81067C94.0012 5.81067 95.1486 6.11571 96.1747 6.72233C97.2007 7.33242 98.0084 8.17476 98.6012 9.25628C99.1905 10.3378 99.4851 11.558 99.4851 12.9203C99.4851 14.2826 99.1905 15.5305 98.6012 16.612C98.0119 17.6935 97.2007 18.5393 96.1747 19.1459C95.1486 19.756 93.9978 20.0576 92.7291 20.0576C91.4604 20.0576 90.3026 19.7526 89.2696 19.1459ZM94.7846 16.9794C95.4121 16.5981 95.9078 16.0539 96.2683 15.3433C96.6322 14.6361 96.8125 13.825 96.8125 12.9168C96.8125 12.0086 96.6322 11.2044 96.2683 10.5042C95.9043 9.80397 95.4086 9.26321 94.7846 8.88191C94.1572 8.5006 93.4709 8.30995 92.7291 8.30995C91.9873 8.30995 91.2974 8.5006 90.6735 8.88191C90.0461 9.26321 89.5504 9.80397 89.1899 10.5042C88.8259 11.2044 88.6456 12.0086 88.6456 12.9168C88.6456 13.825 88.8259 14.6327 89.1899 15.3433C89.5538 16.0504 90.0495 16.5981 90.6735 16.9794C91.3009 17.3607 91.9873 17.5514 92.7291 17.5514C93.4709 17.5514 94.1607 17.3607 94.7846 16.9794Z"></path>
      <path d="M48.8417 19.5756H36.7439V0.5H39.6037V16.851L39.6557 19.5756L42.6541 16.851H48.8417V19.5756Z"></path>
    </svg>
  );
}

```

--------------------------------------------------------------------------------
/demo/next-app/src/app/lingo-dot-dev.tsx:
--------------------------------------------------------------------------------

```typescript
import type { SVGProps } from "react";

export function LingoDotDev(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      width={props.width ? props.width : !props.height ? 150 : undefined}
      height={props.height ? props.height : !props.width ? 26 : undefined}
      viewBox="0 0 150 26"
      fill="#000000"
      xmlns="http://www.w3.org/2000/svg"
      className={props.className}
    >
      <path
        d="M0.0528644 9.3081L9.51858 19.6347C9.55631 19.6754 9.60893 19.6992 9.66454 19.6992H25.1832C25.36 19.6992 25.4483 19.4857 25.3232 19.3606L18.5126 12.5501H13.1508V15.231L6.89523 8.97546H0.198827C0.026055 8.97546 -0.0643027 9.181 0.0528644 9.3081Z"
        fill="#69E300"
      ></path>
      <path
        d="M25.3593 12.2182L15.8926 1.89157C15.8548 1.85086 15.8022 1.82703 15.7466 1.82703H0.227916C0.0501791 1.82703 -0.0381927 2.04051 0.0869179 2.16562L6.8975 8.9762H12.2594V6.29526L18.5149 12.5508H25.2123C25.3851 12.5508 25.4754 12.3453 25.3583 12.2182H25.3593Z"
        fill="#69E300"
      ></path>
      <path d="M104.582 19.7876H101.476V16.7095H104.582V19.7876Z"></path>
      <path d="M109.677 19.1594C108.713 18.5597 107.951 17.7139 107.389 16.6255C106.827 15.537 106.543 14.2995 106.543 12.9199C106.543 11.5402 106.824 10.3097 107.389 9.22814C107.951 8.14662 108.717 7.30775 109.677 6.70807C110.641 6.10838 111.712 5.81027 112.894 5.81027C114.62 5.81027 116 6.46542 117.036 7.77225H117.171V0.711182H119.868V19.7868H117.553L117.279 18.0432H117.143C116.09 19.3882 114.672 20.0607 112.894 20.0607C111.712 20.0607 110.641 19.7626 109.677 19.1629V19.1594ZM115.195 16.979C115.802 16.5977 116.284 16.0535 116.641 15.3429C116.994 14.6357 117.171 13.8246 117.171 12.9164C117.171 12.0082 116.994 11.204 116.641 10.5038C116.287 9.80357 115.805 9.26281 115.195 8.8815C114.585 8.5002 113.927 8.30955 113.22 8.30955C112.512 8.30955 111.829 8.5002 111.23 8.8815C110.63 9.26281 110.152 9.80357 109.798 10.5038C109.445 11.204 109.268 12.0082 109.268 12.9164C109.268 13.8246 109.445 14.6565 109.798 15.3568C110.152 16.057 110.63 16.5977 111.23 16.979C111.829 17.3603 112.492 17.551 113.22 17.551C113.947 17.551 114.585 17.3603 115.195 16.979Z"></path>
      <path d="M126.219 16.6632C127.051 17.2802 127.901 17.7135 128.972 17.7135C129.734 17.7135 130.407 17.5402 130.989 17.197C131.572 16.8504 132.005 16.4067 132.296 15.8625H135.104C134.684 17.0792 133.95 18.0844 132.896 18.8748C131.842 19.6651 130.535 20.0603 128.972 20.0603C127.7 20.0603 126.545 19.7552 125.512 19.1486C124.476 18.542 123.665 17.6962 123.072 16.6147C122.483 15.5332 122.188 14.3026 122.188 12.923C122.188 11.5433 122.483 10.3405 123.072 9.25896C123.661 8.17744 124.476 7.33511 125.512 6.72502C126.549 6.1184 127.7 5.81335 128.972 5.81335C130.244 5.81335 131.291 6.10453 132.282 6.68689C133.274 7.26925 134.053 8.06652 134.625 9.08564C135.197 10.1048 135.485 11.2487 135.485 12.5174C135.485 13.1517 135.44 13.6336 135.35 13.9629H124.874L127.121 11.8934H132.819C132.729 10.805 132.327 9.90371 131.62 9.19657C130.913 8.48942 130.029 8.13238 128.979 8.13238C127.928 8.13238 126.972 8.48595 126.226 9.19657C125.481 9.90371 125.037 10.805 124.892 11.8934C124.892 11.8934 124.316 15.2628 126.226 16.6736L126.219 16.6632Z"></path>
      <path d="M144.556 19.7876H140.605L135.783 6.08142H138.618L142.324 16.7372H142.868L146.574 6.08142H149.409L144.56 19.7876H144.556Z"></path>
      <path d="M53.4117 3.49132H50.4688V0.766724H53.4117V3.49132ZM53.2765 19.7869H50.5797V6.08073H53.2765V19.7869Z"></path>
      <path d="M56.2451 19.7872V6.08105H58.5607L58.8345 7.49881H58.9697C59.3129 7.06204 59.8398 6.6738 60.5504 6.32716C61.2575 5.98052 62.0756 5.81067 63.0046 5.81067C64.0584 5.81067 64.9978 6.05332 65.8263 6.53168C66.6513 7.01351 67.2995 7.68946 67.7605 8.563C68.225 9.43653 68.4538 10.4349 68.4538 11.5614V19.7907H65.7569V11.7798C65.7569 10.7988 65.438 9.98076 64.8037 9.32561C64.1693 8.67045 63.379 8.34461 62.4327 8.34461C61.7983 8.34461 61.2125 8.5006 60.6752 8.80911C60.1379 9.11762 59.7185 9.53706 59.4065 10.064C59.098 10.5908 58.942 11.1628 58.942 11.7798V19.7907H56.2451V19.7872Z"></path>
      <path d="M73.9972 24.772C73.0613 24.2832 72.3472 23.6697 71.8585 22.9313C71.3697 22.193 71.1062 21.4477 71.0681 20.6817H73.7927C73.8655 21.316 74.2121 21.8776 74.8292 22.3559C75.4462 22.8378 76.3024 23.0769 77.3908 23.0769C78.4793 23.0769 79.4152 22.758 80.0877 22.1237C80.7602 21.4859 81.0964 20.6435 81.0964 19.5897V17.4094H80.9612C80.4898 17.9363 79.897 18.3557 79.1899 18.6642C78.4828 18.9727 77.6993 19.1287 76.8466 19.1287C75.6646 19.1287 74.6004 18.8479 73.6436 18.2829C72.6904 17.7213 71.9416 16.931 71.3974 15.9119C70.8532 14.8962 70.5793 13.7419 70.5793 12.4524C70.5793 11.1629 70.8532 10.0121 71.3974 9.00679C71.9416 7.99807 72.6904 7.21466 73.6436 6.64964C74.5969 6.08808 75.6646 5.80383 76.8466 5.80383C77.7201 5.80383 78.5209 5.97715 79.2592 6.32033C79.9941 6.66697 80.5903 7.128 81.0444 7.71036H81.1796L81.4535 6.07421H83.7968V19.6175C83.7968 20.7787 83.5437 21.8048 83.0341 22.6956C82.5246 23.5865 81.7862 24.2763 80.8122 24.7651C79.8416 25.2573 78.7011 25.5 77.3908 25.5C76.0805 25.5 74.9332 25.2538 73.9972 24.7651V24.772ZM79.1726 16.1476C79.7619 15.794 80.2298 15.2949 80.5765 14.6501C80.9231 14.0054 81.093 13.2739 81.093 12.4559C81.093 11.6378 80.9196 10.9133 80.5765 10.2755C80.2298 9.64115 79.7619 9.14545 79.1726 8.79188C78.5833 8.4383 77.9247 8.26152 77.1967 8.26152C76.0701 8.26152 75.1411 8.65322 74.4028 9.43316C73.6679 10.2131 73.3005 11.2218 73.3005 12.4593C73.3005 13.6968 73.6679 14.7298 74.4028 15.5098C75.1377 16.2897 76.0701 16.6814 77.1967 16.6814C77.9247 16.6814 78.5833 16.5046 79.1726 16.1511V16.1476Z"></path>
      <path d="M89.2696 19.1459C88.2331 18.5393 87.422 17.6935 86.8292 16.612C86.24 15.5305 85.9453 14.2999 85.9453 12.9203C85.9453 11.5406 86.24 10.3378 86.8292 9.25628C87.4185 8.17476 88.2331 7.33242 89.2696 6.72233C90.3061 6.11571 91.4569 5.81067 92.7291 5.81067C94.0012 5.81067 95.1486 6.11571 96.1747 6.72233C97.2007 7.33242 98.0084 8.17476 98.6012 9.25628C99.1905 10.3378 99.4851 11.558 99.4851 12.9203C99.4851 14.2826 99.1905 15.5305 98.6012 16.612C98.0119 17.6935 97.2007 18.5393 96.1747 19.1459C95.1486 19.756 93.9978 20.0576 92.7291 20.0576C91.4604 20.0576 90.3026 19.7526 89.2696 19.1459ZM94.7846 16.9794C95.4121 16.5981 95.9078 16.0539 96.2683 15.3433C96.6322 14.6361 96.8125 13.825 96.8125 12.9168C96.8125 12.0086 96.6322 11.2044 96.2683 10.5042C95.9043 9.80397 95.4086 9.26321 94.7846 8.88191C94.1572 8.5006 93.4709 8.30995 92.7291 8.30995C91.9873 8.30995 91.2974 8.5006 90.6735 8.88191C90.0461 9.26321 89.5504 9.80397 89.1899 10.5042C88.8259 11.2044 88.6456 12.0086 88.6456 12.9168C88.6456 13.825 88.8259 14.6327 89.1899 15.3433C89.5538 16.0504 90.0495 16.5981 90.6735 16.9794C91.3009 17.3607 91.9873 17.5514 92.7291 17.5514C93.4709 17.5514 94.1607 17.3607 94.7846 16.9794Z"></path>
      <path d="M48.8417 19.5756H36.7439V0.5H39.6037V16.851L39.6557 19.5756L42.6541 16.851H48.8417V19.5756Z"></path>
    </svg>
  );
}

```
Page 7/16FirstPrevNextLast