{"id":33280905,"url":"https://github.com/flameinthedark/locail","last_synced_at":"2025-11-17T12:03:38.606Z","repository":{"id":322584022,"uuid":"1089431625","full_name":"FlameInTheDark/locail","owner":"FlameInTheDark","description":"Translate localization files using LLM","archived":false,"fork":false,"pushed_at":"2025-11-05T07:53:05.000Z","size":2236,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-05T09:19:17.574Z","etag":null,"topics":["csv","i18n","llm","localization","localization-tool","ollama","openrouter","paraglide","translation","vdf"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlameInTheDark.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-11-04T10:35:07.000Z","updated_at":"2025-11-05T09:11:01.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/FlameInTheDark/locail","commit_stats":null,"previous_names":["flameinthedark/locail"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/FlameInTheDark/locail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlameInTheDark%2Flocail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlameInTheDark%2Flocail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlameInTheDark%2Flocail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlameInTheDark%2Flocail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlameInTheDark","download_url":"https://codeload.github.com/FlameInTheDark/locail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlameInTheDark%2Flocail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284877005,"owners_count":27077734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-17T02:00:06.431Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csv","i18n","llm","localization","localization-tool","ollama","openrouter","paraglide","translation","vdf"],"created_at":"2025-11-17T12:03:35.717Z","updated_at":"2025-11-17T12:03:38.598Z","avatar_url":"https://github.com/FlameInTheDark.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# locail\n\nLLM‑assisted localization desktop app. Import translation files (Paraglide i18n JSON, CSV, Valve/HL VDF), translate missing strings with your preferred LLM provider (OpenRouter or Ollama), review and edit, then export back to the original or another format.\n\nThe app is built with Wails (Go + React + Vite) and stores data locally in SQLite. No cloud backend.\n\n## Features\n\n- Import formats: Paraglide i18n JSON (flat key→string), CSV (`key, source[, context]`), Valve/HL VDF\n- Translate via LLM providers: OpenRouter and Ollama\n- Model discovery and connection test per provider\n- Job‑based translation: translate one row, a selection, or an entire file\n- Placeholder and Valve tag preservation with validation\n- Local translation cache to avoid repeating identical work\n- Export to original format or to another supported format (JSON/CSV/VDF)\n- Keyboard shortcuts: `/` focuses search; `Ctrl/Cmd+S` saves\n\n## Quick Start\n\nPrerequisites:\n\n- Go 1.23+\n- Node.js 16+ (or newer LTS)\n- Wails CLI: `go install github.com/wailsapp/wails/v2/cmd/wails@latest`\n\nInstall deps and run in development:\n\n1) Frontend dependencies\n\n```\ncd frontend \u0026\u0026 npm install\n```\n\n2) Live development (desktop app with hot reload)\n\n```\nwails dev\n```\n\nBuild for production:\n\n```\nwails build\n./build/bin/locail\n```\n\nFrontend‑only dev server (optional):\n\n```\ncd frontend \u0026\u0026 npm run dev\n```\n\n## Usage\n\n1) Create a project\n\n- Open the app and go to Projects\n- Create a project and set its source language (e.g., `en`)\n- Add target locales in Edit Project when needed\n\n2) Configure a provider (Settings)\n\n- Add a provider and choose its type:\n  - `openrouter`: requires API key; optional custom base URL (defaults to `https://openrouter.ai`)\n  - `ollama`: no key; base URL typically `http://localhost:11434`\n- Load models to discover available model IDs and select a default\n- Use Test to verify connectivity and JSON output\n\n3) Import translation files (Files → Import)\n\n- Supported formats:\n  - Paraglide JSON: a flat JSON object of `key: value` pairs\n  - CSV: header must include `key` and a source column (`source`/`value`/`text`/`default`); optional `context`\n  - Valve/HL VDF: reads pairs from the `tokens { ... }` block\n- Provide the file’s locale (e.g., `en`)\n\n4) Translate\n\n- Select a file and target language\n- Pick the provider in the toolbar\n- Translate a single row, a selection, or use “Translate Selected” to start a job\n- Progress, current item, and last result are streamed via app events\n- Edits can be made inline and saved at any time (`Ctrl/Cmd+S`)\n\n5) Export\n\n- Use Export and choose:\n  - Original format or override to JSON/CSV/VDF\n  - For VDF, set Language Name used in the header\n  - For CSV, choose separator (comma/semicolon/tab)\n\n## Translation Behavior\n\n- Prompts instruct the model to return strict JSON: `{ \"translation\": \"...\" }`\n- The app masks placeholders like `{name}` and Valve tags (e.g., `\u003csfx\u003e`, `\u003cclr:...\u003e`) before calling the model, then unmasks them after\n- Output is validated to ensure placeholders and tags are preserved; failures are logged and retried briefly\n- Identical source strings are cached locally by provider/model to reduce cost and latency\n\n## Data \u0026 Storage\n\n- SQLite database: `data/locail.db`\n- Providers (including API keys), files, units, translations, jobs, logs, prompt templates, and cache are stored locally\n- API keys are masked in the UI and kept only in the local database; do not commit the `data/` directory\n\n## Supported Providers\n\n- OpenRouter\n  - Base URL: `https://openrouter.ai` (default) or a compatible API endpoint\n  - Requires API key\n  - Model discovery and normalization supported\n- Ollama\n  - Base URL: `http://localhost:11434` (default)\n  - Local models only; list available models via `/api/tags`\n\nIf a provider fails to produce valid JSON, the runner retries a few times and logs the cause.\n\n## Supported Formats\n\n- Paraglide i18n JSON (.json)\n- CSV (.csv)\n  - Columns: `key`, source (`source`/`value`/`text`/`default`), optional `context`\n- Valve/HL VDF (.vdf)\n  - Reads and writes under `lang { language ... tokens { \"key\" \"value\" } }`\n\n## Project Structure\n\n- Go (Wails) backend: `main.go`, `app.go`; config in `wails.json`\n- Frontend (React + TypeScript + Vite): `frontend/` (`src/main.tsx`, `src/App.tsx`, assets in `src/assets/`)\n- Generated Wails bindings: `frontend/wailsjs/**` (regenerated by Wails; do not edit)\n- Build artifacts: `build/**`; production assets in `frontend/dist` are embedded via `go:embed`\n\nClean architecture (selected parts):\n\n- `internal/domain`: entities (Project, File, Unit, Translation, Provider, Job, Template, Cache)\n- `internal/ports`: repository and provider interfaces\n- `internal/usecase`: application services (importer, exporter, translator, jobs)\n- `internal/adapters`: SQLite repositories, parsers (JSON/CSV/VDF), exporters (JSON/CSV/VDF), LLM HTTP providers, prompt renderer\n\n## Development\n\n- Install frontend deps: `cd frontend \u0026\u0026 npm install`\n- Live development (Go + frontend): `wails dev`\n- Frontend only dev server: `cd frontend \u0026\u0026 npm run dev`\n- Frontend build + type‑check: `cd frontend \u0026\u0026 npm run build`\n- Production desktop build: `wails build` (binary in `build/bin/locail`)\n\nNotes:\n\n- Never edit `frontend/wailsjs/**`; run `wails dev` or `wails build` to regenerate\n- Ensure `gofmt -s -w .` and `go vet ./...` pass before committing changes to Go code\n- Images/fonts should live in `frontend/src/assets/` so Vite bundles them\n\n## Troubleshooting\n\n- Wails CLI not found: install via `go install github.com/wailsapp/wails/v2/cmd/wails@latest`\n- Frontend deps missing: run `cd frontend \u0026\u0026 npm install`\n- OpenRouter errors (401/403): verify API key and base URL, then use the Test button\n- Ollama connection failed: ensure the daemon is running on `http://localhost:11434` and the model is available\n- No models listed: click Load models in the provider editor or enter a model ID manually\n- JSON parse failures: the runner retries briefly; if persistent, try a different model or adjust the default model for the provider\n\n## Security\n\n- Do not commit secrets. API keys are stored locally in SQLite and masked in the UI\n- Review `wails.json` before modifying build hooks\n\n## License\n\nNo license has been declared for this repository yet.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflameinthedark%2Flocail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflameinthedark%2Flocail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflameinthedark%2Flocail/lists"}