{"id":22447184,"url":"https://github.com/edspencer/react-auto-intl","last_synced_at":"2025-10-16T05:31:53.722Z","repository":{"id":264247043,"uuid":"892823832","full_name":"edspencer/react-auto-intl","owner":"edspencer","description":"Uses AI to automatically internationalize and translate your React and Next JS applications.","archived":false,"fork":false,"pushed_at":"2024-12-10T21:04:14.000Z","size":220,"stargazers_count":2,"open_issues_count":11,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-28T16:15:47.537Z","etag":null,"topics":["ai","next-intl","nextjs","react","react-intl","vercel-ai-sdk"],"latest_commit_sha":null,"homepage":"https://edspencer.net/projects","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/edspencer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2024-11-22T21:10:14.000Z","updated_at":"2024-12-19T03:30:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"082cf3d0-e490-40a5-ad99-af52bc193f95","html_url":"https://github.com/edspencer/react-auto-intl","commit_stats":null,"previous_names":["edspencer/next-auto-intl"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edspencer%2Freact-auto-intl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edspencer%2Freact-auto-intl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edspencer%2Freact-auto-intl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edspencer%2Freact-auto-intl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edspencer","download_url":"https://codeload.github.com/edspencer/react-auto-intl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236684480,"owners_count":19188642,"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","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":["ai","next-intl","nextjs","react","react-intl","vercel-ai-sdk"],"created_at":"2024-12-06T04:15:04.292Z","updated_at":"2025-10-16T05:31:48.341Z","avatar_url":"https://github.com/edspencer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React Internationalization, meet AI\n\n**react-auto-intl** automates the internationalization (i18n) process for React applications. It works great with the excellent [react-intl](https://formatjs.github.io/docs/react-intl/) and [next-intl](https://next-intl-docs.vercel.app/) libraries, and does 3 things:\n\n1. automatically detects all of the user-facing strings in your React components, **extracting** into your i18n framework's storage format for you\n2. automatically **rewrites** your JSX components to use `next-intl` instead of hard-coded strings\n3. automatically **translates** all of the user-facing strings into any number of languages, using an LLM of your choice\n\nYou can opt in or out of any of these steps, and you can run the process any number of times, so you can work in your native language and have confidence that most of the internationalization work will be done by a single fast CLI command.\n\n## Features\n\n- **Automatic String Extraction**: Detects and extracts user-facing strings from JSX elements and attributes like `placeholder`, `title`, `aria-label`, etc.\n- **Source File Updates**: Replaces hardcoded strings in your React components with translation calls using `useTranslations`.\n- **JSON Message File Management**: Generates and updates language-specific JSON files for `next-intl`.\n- **LLM Integration**: Supports automated translations into target languages using an LLM (optional).\n- **Eslint Integration**: Runs `eslint --fix` on updated source files for consistent formatting.\n\n---\n\n## Installation\n\nInstall the library via npm or yarn:\n\n```bash\nnpm install react-auto-intl\n```\n\nor\n\n```bash\nyarn add react-auto-intl\n```\n\nBy default, `react-auto-intl` will use OpenAI's `gpt-4o-mini` model to perform translations, so you need to have this environment variable set somewhere:\n\n```sh\nOPENAI_API_KEY=\"your-openai-api-key\"\n```\n\n---\n\n## Usage\n\n### 1. Basic Configuration\n\nGenerate the `react-auto-intl` config file:\n\n```sh\nnpx rai generate\n```\n\nThis will create `i18n/auto-intl.config.mjs`, which looks like this by default:\n\n```javascript\n//These are all actually the default values, shown here just so you can see the options\nconst config = {\n  scanDirs: ['./app', './components'], // Directories to scan for components\n  baseLanguage: 'en', // The base language for the application\n  targetLanguages: ['fr', 'pt'], // Optional: target languages for translation\n  messagesDir: './i81n/messages', // Directory to store translation JSON files\n  rewriteSourceFiles: true, // Enable source file updates\n  lintAfterRewrite: true, // Run eslint --fix after rewriting files\n};\n\nexport default config;\n```\n\nSee further down this file for a full explanation of the various Configuration options.\n\n### 2. Auto-Internationalizing\n\n`react-auto-intl` does 3 things:\n\n1. Extracts all user-facing strings in your JSX components and writes them to {baseLanguage}.json\n2. Rewrites JSX with hard-coded strings to pull the value from {someLanguage}.json\n3. Translates {baseLanguage}.json into up to 40 other languages, using an LLM of your choice\n\nTo do all 3, run this command:\n\n```sh\nnpx rai run\n```\n\nThis will spit out a bunch of logs as it goes through the extraction, rewriting and translation process. It's a good idea to do this on a clean new branch, as the `rewrite` step is going to modify your source code (see example below).\n\nIt is safe to run the task any number of times. If you've already started adding `next-intl` to your app, `react-auto-intl` should run just fine to finish the string extract process for you.\n\nAfter this command has run, you should see `en.json` fully populated, all of your JSX React components with hard-coded strings updated to use the `next-intl` string, and full translation files also created for whichever languages you specified you want support for.\n\n### 3. Example Output\n\nLet's say you have this component:\n\n#### Input Component\n\n```tsx\nexport const GuestModeMessage = ({ delay }: { delay?: number }) =\u003e {\n  return (\n    \u003cdiv className=\"bg-yellow-50 p-2 rounded-lg text-sm\"\u003e\n      \u003cp\u003e\n        You\u0026apos;re using \u003cstrong\u003eguest mode\u003c/strong\u003e. Click{' '}\n        \u003cLink className=\"font-bold underline\" href=\"/api/auth/signin\"\u003e\n          register\n        \u003c/Link\u003e{' '}\n        at any time to create an account and keep all the items you added.\n      \u003c/p\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n#### Output Component (Updated)\n\nAfter running the `rewrite` phase of the process, the component will have been updated to look like this:\n\n```tsx\nimport { useTranslations } from 'next-intl';\n\nexport const GuestModeMessage = ({ delay }: { delay?: number }) =\u003e {\n  const t = useTranslations('GuestModeMessage');\n\n  return (\n    \u003cdiv className=\"bg-yellow-50 p-2 rounded-lg text-sm\"\u003e\n      \u003cp\u003e\n        {t('youre-using')} \u003cstrong\u003e{t('guest-mode')}\u003c/strong\u003e. {t('click')}{' '}\n        \u003cLink className=\"font-bold underline\" href=\"/api/auth/signin\"\u003e\n          {t('register')}\n        \u003c/Link\u003e{' '}\n        {t('at-any-time-to-create')}\n      \u003c/p\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n#### Generated JSON (`messages/en.json`)\n\n```json\n{\n  \"GuestModeMessage\": {\n    \"youre-using\": \"You're using\",\n    \"guest-mode\": \"guest mode\",\n    \"click\": \"Click\",\n    \"register\": \"register\",\n    \"at-any-time-to-create\": \"at any time to create an account and keep all the items you added.\"\n  }\n}\n```\n\n#### Generated JSON (`messages/fr.json`)\n\n```json\n{\n  \"GuestModeMessage\": {\n    \"youre-using\": \"Vous utilisez\",\n    \"guest-mode\": \"mode invité\",\n    \"click\": \". Cliquez\",\n    \"register\": \"s'inscrire\",\n    \"at-any-time-to-create\": \"à tout moment pour créer un compte et conserver tous les éléments que vous avez ajoutés.\"\n  }\n}\n```\n\n#### Generated JSON (`messages/pt.json`)\n\n```json\n{\n  \"GuestModeMessage\": {\n    \"youre-using\": \"Você está usando\",\n    \"guest-mode\": \"modo convidado\",\n    \"click\": \". Clique\",\n    \"register\": \"registrar\",\n    \"at-any-time-to-create\": \"a qualquer momento para criar uma conta e manter todos os itens que você adicionou.\"\n  }\n}\n```\n\n---\n\n### 4. Configuration\n\nPass a configuration object to customize the behavior of **react-auto-intl**.\n\n```typescript\nexport type Configuration = {\n  scanDirs: string[]; // Directories to scan for components\n  baseLanguage: string; // Base language (e.g., \"en\")\n  targetLanguages?: string[]; // Optional: target languages for translations\n  messagesDir?: string; // Directory for JSON message files\n  allowDuplicateComponentNames?: boolean; // Allow duplicate component names across files\n  rewriteSourceFiles?: boolean; // Rewrite source files with translation hooks\n  lintAfterRewrite?: boolean; // Run eslint --fix after updating files\n  deleteUnusedTranslations?: boolean; // Delete unused keys from JSON files\n  componentWhitelist?: string[]; // Only process specific components\n  parallelTranslations: 5; //max number of parallelization jobs to run in parallel\n};\n```\n\n---\n\n### 5. Other CLI commands\n\n#### scan\n\nTo just scan for internationalizable strings in your project without modifying any files, just run this command:\n\n```sh\nnpx rai scan\n```\n\n#### extract\n\nTo just extract all the detected strings in your JSX components and write them to `i18n/messages/en.json` (assuming your configured `baseLanguage` is set to `en`), just run this command:\n\n```sh\nnpx rai extract\n```\n\nIt is safe to run the task any number of times.\n\n#### rewrite\n\nThe `rewrite` phase iterates through all of strings in `i18n/messages/en.json` and updates all of the JSX components\n\nTo just run the `rewrite` phase:\n\n```sh\nnpx rai rewrite\n```\n\nIt is safe to run the task any number of times.\n\n#### translate\n\nYou can just run the `translate` command if you don't want to re-scan/rewrite your JSX files. Useful when adding another language to `targetLanguages`, for example:\n\n```sh\nnpx rai translate\n```\n\nThis will create a `{someLanguage}.json` file for each language in the `targetLanguages` config array. If some or all all expected translations for the target language already exist, it will not re-translate them, just the strings it doesn't have a translation for currently.\n\n## Contributing\n\nContributions are welcome! Please open issues or submit pull requests on the [GitHub repository](https://github.com/edspencer/react-auto-intl).\n\n---\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedspencer%2Freact-auto-intl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedspencer%2Freact-auto-intl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedspencer%2Freact-auto-intl/lists"}