[
  {
    "path": ".all-contributorsrc",
    "content": "{\n  \"projectName\": \"extract-react-intl-messages\",\n  \"projectOwner\": \"akameco\",\n  \"files\": [\"readme.md\"],\n  \"imageSize\": 100,\n  \"commit\": true,\n  \"contributors\": [\n    {\n      \"login\": \"akameco\",\n      \"name\": \"akameco\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/4002137?v=4\",\n      \"profile\": \"http://akameco.github.io\",\n      \"contributions\": [\"code\", \"test\", \"doc\", \"infra\"]\n    },\n    {\n      \"login\": \"hoantran-it\",\n      \"name\": \"Hoan Tran\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/13161875?v=4\",\n      \"profile\": \"http://hoantran.info\",\n      \"contributions\": [\"code\", \"test\"]\n    },\n    {\n      \"login\": \"giantpinkwalrus\",\n      \"name\": \"giantpinkwalrus\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/3383240?v=4\",\n      \"profile\": \"https://github.com/giantpinkwalrus\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"enrique-ramirez\",\n      \"name\": \"enrique-ramirez\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1190640?v=4\",\n      \"profile\": \"https://github.com/enrique-ramirez\",\n      \"contributions\": [\"doc\"]\n    },\n    {\n      \"login\": \"hoschi\",\n      \"name\": \"Stefan Gojan\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/163128?v=4\",\n      \"profile\": \"http://stefan-gojan.de\",\n      \"contributions\": [\"bug\", \"code\", \"test\"]\n    },\n    {\n      \"login\": \"solomon23\",\n      \"name\": \"Solomon English\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/857744?v=4\",\n      \"profile\": \"https://lithe.net\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"Filson14\",\n      \"name\": \"Filip \\\"Filson\\\" Pasternak\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/4540538?v=4\",\n      \"profile\": \"https://github.com/Filson14\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"nodaguti\",\n      \"name\": \"nodaguti\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/27622?v=4\",\n      \"profile\": \"http://about.me/nodaguti\",\n      \"contributions\": [\"code\", \"test\"]\n    },\n    {\n      \"login\": \"fix-fix\",\n      \"name\": \"fix-fix\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/11943024?v=4\",\n      \"profile\": \"https://github.com/fix-fix\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"bradbarrow\",\n      \"name\": \"bradbarrow\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1264276?v=4\",\n      \"profile\": \"http://bradbarrow.com\",\n      \"contributions\": [\"bug\", \"code\", \"test\"]\n    },\n    {\n      \"login\": \"gmaclennan\",\n      \"name\": \"Gregor MacLennan\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/290457?v=4\",\n      \"profile\": \"http://ddem.us/\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"zarv1k\",\n      \"name\": \"Dmitry Zarva\",\n      \"avatar_url\": \"https://avatars1.githubusercontent.com/u/6296643?v=4\",\n      \"profile\": \"https://github.com/zarv1k\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"panpanc\",\n      \"name\": \"Michael Pan\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/29132669?v=4\",\n      \"profile\": \"https://github.com/panpanc\",\n      \"contributions\": [\"example\"]\n    },\n    {\n      \"login\": \"testower\",\n      \"name\": \"Tom Erik Støwer\",\n      \"avatar_url\": \"https://avatars2.githubusercontent.com/u/231492?v=4\",\n      \"profile\": \"https://github.com/testower\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"lensbart\",\n      \"name\": \"Bart Lens\",\n      \"avatar_url\": \"https://avatars0.githubusercontent.com/u/20876627?v=4\",\n      \"profile\": \"https://nextbook.io\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"revskill10\",\n      \"name\": \"Truong Hoang Dung\",\n      \"avatar_url\": \"https://avatars3.githubusercontent.com/u/1390196?v=4\",\n      \"profile\": \"https://github.com/revskill10\",\n      \"contributions\": [\"example\"]\n    },\n    {\n      \"login\": \"Nestoro\",\n      \"name\": \"Nestoro\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/13397845?v=4\",\n      \"profile\": \"https://github.com/Nestoro\",\n      \"contributions\": [\"code\"]\n    },\n    {\n      \"login\": \"lightnet328\",\n      \"name\": \"Yutaro Kido\",\n      \"avatar_url\": \"https://avatars.githubusercontent.com/u/2351326?v=4\",\n      \"profile\": \"https://lightnet328.com/\",\n      \"contributions\": [\"code\"]\n    }\n  ],\n  \"repoType\": \"github\",\n  \"commitConvention\": \"none\",\n  \"repoHost\": \"https://github.com\",\n  \"skipCi\": true,\n  \"contributorsPerLine\": 7\n}\n\n"
  },
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"targets\": {\n          \"node\": \"current\"\n        }\n      }\n    ],\n    \"@babel/preset-react\"\n  ]\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"extends\": [\"precure/auto\"],\n  \"rules\": {\n    \"@typescript-eslint/explicit-function-return-type\": \"off\"\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\n*.js text eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "<!--\nThanks for your interest in the project.\nI appreciate bugs filed and PRs submitted!\nI'll probably ask you to submit the fix (after giving some direction).\n\nEnglish/日本語(日本語で入力して大丈夫です。日本語の方が迅速です)\n-->\n\n- version:\n- `node` version:\n- `npm` (or `yarn`) version:\n\n**Do you want to request a *feature* or report a *bug*?:**\n\n**What is the current behavior?:**\n\n**What is the expected behavior?:**\n\n**Suggested solution:**\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nThanks for your interest in the project. I appreciate bugs filed and PRs submitted!\nEnglish/日本語(日本語で入力して大丈夫です。日本語の方が迅速です)\n-->\n\n<!-- What changes are being made? (What feature/bug is being fixed here?) / 何が変更されていますか？-->\n**What**:\n\n\n<!-- Why are these changes necessary? / なぜその変更をする必要がありましたか？-->\n**Why**:\n\n\n<!-- How were these changes implemented? / これらの変更をどのように実装しましたか？-->\n**How**:\n\n\n**Checklist**:\n<!-- add \"N/A\" to the end of each line that's irrelevant to your changes to check an item, place an \"x\" in the box like so: \"- [x] Documentation\" -->\n\n* [ ] Documentation\n* [ ] Tests\n* [ ] Ready to be merged <!-- In your opinion, is this ready to be merged as soon as it's reviewed? -->\n\n<!-- feel free to add additional comments. -->\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: test\n\non: [push]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        # LTS (20.x) and latest (22.x) only\n        node-version: [20.x, 22.x]\n    steps:\n      - uses: actions/checkout@v2\n      - name: Setup node\n        uses: actions/setup-node@v1\n        with:\n          node-version: ${{ matrix.node }}\n      - run: npm install\n      - run: npm run lint\n      - run: npm run test\n"
  },
  {
    "path": ".gitignore",
    "content": "# Dependencies\nnode_modules/\n\n# Build outputs\nlib/\ndist/\ncompiled/\n\n# Cache files\n.eslintcache\n.test-cache\n\n# OS files\n.DS_Store\nThumbs.db\n\n# IDE files\n.vscode/\n.idea/\n*.swp\n*.swo\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Coverage directory used by tools like istanbul\ncoverage/\n.nyc_output/\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "npx lint-staged\n"
  },
  {
    "path": ".prettierignore",
    "content": "**/test/fixtures/**\n.github\ndist\npackage.json\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"semi\": false,\n  \"singleQuote\": true,\n  \"trailingComma\": \"none\"\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n- Using welcoming and inclusive language\n- Being respectful of differing viewpoints and experiences\n- Gracefully accepting constructive criticism\n- Focusing on what is best for the community\n- Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery and unwelcome sexual attention or advances\n- Trolling, insulting/derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or electronic address, without explicit permission\n- Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at akameco.t@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "eslint.config.mjs",
    "content": "// ESLint v9+ config\nimport js from '@eslint/js'\nimport tseslint from 'typescript-eslint'\n\nexport default [\n  js.configs.recommended,\n  ...tseslint.configs.recommended,\n  {\n    files: ['src/**/*.ts'],\n    languageOptions: {\n      parser: tseslint.parser,\n      parserOptions: {\n        ecmaVersion: 2022,\n        sourceType: 'module'\n      }\n    }\n  },\n  {\n    ignores: ['dist/', 'node_modules/', 'compiled/']\n  }\n]\n"
  },
  {
    "path": "example/basic/babel.config.js",
    "content": "module.exports = function (api) {\n  api.cache(true)\n\n  return {\n    presets: ['react-app']\n  }\n}\n"
  },
  {
    "path": "example/basic/i18n/.keep",
    "content": ""
  },
  {
    "path": "example/basic/i18n/en.json",
    "content": "{\n  \"App\": {\n    \"hello\": \"Hello Button\",\n    \"submit\": \"Submit Button\"\n  },\n  \"a\": {\n    \"hello\": \"hello\",\n    \"world\": \"world\"\n  }\n}\n"
  },
  {
    "path": "example/basic/i18n/ja.json",
    "content": "{\n  \"App\": {\n    \"hello\": \"\",\n    \"submit\": \"\"\n  },\n  \"a\": {\n    \"hello\": \"\",\n    \"world\": \"\"\n  }\n}\n"
  },
  {
    "path": "example/basic/package.json",
    "content": "{\n  \"name\": \"basic\",\n  \"version\": \"1.0.0\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"i18n\": \"NODE_ENV=development extract-messages -l=en,ja -o i18n -d en 'src/**/*.{js,jsx}'\"\n  },\n  \"dependencies\": {\n    \"react\": \"^16.13.1\",\n    \"react-intl\": \"^4.3.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.9.0\",\n    \"babel-preset-react-app\": \"^9.1.2\",\n    \"extract-react-intl-messages\": \"latest\"\n  }\n}\n"
  },
  {
    "path": "example/basic/src/App.jsx",
    "content": "import React from 'react'\nimport { injectIntl, useIntl } from 'react-intl'\n\nexport const SubmitButton = injectIntl(({ intl }) => {\n  const label = intl.formatMessage({\n    id: 'App.submit',\n    defaultMessage: 'Submit Button'\n  })\n  return <button aria-label={label}>{label}</button>\n})\n\nexport const HelloButton = () => {\n  const intl = useIntl()\n  const label = intl.formatMessage({\n    id: 'App.hello',\n    defaultMessage: 'Hello Button'\n  })\n  return <button aria-label={label}>{label}</button>\n}\n"
  },
  {
    "path": "example/basic/src/messages.js",
    "content": "/* eslint-disable import/no-extraneous-dependencies */\nimport { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'a.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "example/with-typescript/babel.config.js",
    "content": "module.exports = function (api) {\n  api.cache(true)\n\n  return {\n    presets: ['@babel/preset-react', '@babel/preset-typescript']\n  }\n}\n"
  },
  {
    "path": "example/with-typescript/i18n/en.json",
    "content": "{\n  \"App\": {\n    \"hello\": \"Hello Button\",\n    \"submit\": \"Submit Button\"\n  },\n  \"a\": {\n    \"hello\": \"hello\",\n    \"world\": \"world\"\n  }\n}\n"
  },
  {
    "path": "example/with-typescript/i18n/ja.json",
    "content": "{\n  \"App\": {\n    \"hello\": \"\",\n    \"submit\": \"\"\n  },\n  \"a\": {\n    \"hello\": \"\",\n    \"world\": \"\"\n  }\n}\n"
  },
  {
    "path": "example/with-typescript/package.json",
    "content": "{\n  \"name\": \"with-typescript\",\n  \"version\": \"1.0.0\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"i18n\": \"extract-messages -l=en,ja -o i18n -d en 'src/**/*.{ts,tsx}'\"\n  },\n  \"dependencies\": {\n    \"react\": \"^16.13.1\",\n    \"react-intl\": \"^4.3.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.9.0\",\n    \"@babel/preset-react\": \"^7.9.4\",\n    \"@babel/preset-typescript\": \"^7.9.0\",\n    \"extract-react-intl-messages\": \"latest\",\n    \"typescript\": \"^3.8.3\"\n  }\n}\n"
  },
  {
    "path": "example/with-typescript/src/App.tsx",
    "content": "import React from 'react'\nimport { injectIntl, useIntl } from 'react-intl'\n\nexport const SubmitButton = injectIntl(({ intl }) => {\n  const label = intl.formatMessage({\n    id: 'App.submit',\n    defaultMessage: 'Submit Button'\n  })\n  return <button aria-label={label}>{label}</button>\n})\n\nexport const HelloButton = () => {\n  const intl = useIntl()\n  const label = intl.formatMessage({\n    id: 'App.hello',\n    defaultMessage: 'Hello Button'\n  })\n  return <button aria-label={label}>{label}</button>\n}\n"
  },
  {
    "path": "example/with-typescript/src/messages.ts",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'a.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "jest.config.js",
    "content": "export default {\n  testPathIgnorePatterns: [\n    '<rootDir>[/\\\\\\\\](dist|compiled|node_modules)[/\\\\\\\\]'\n  ],\n  testEnvironment: 'node',\n  preset: 'ts-jest',\n  extensionsToTreatAsEsm: ['.ts'],\n  moduleNameMapper: {\n    '^(\\\\.{1,2}/.*)\\\\.js$': '$1'\n  },\n  transform: {\n    '^.+\\\\.ts$': [\n      'ts-jest',\n      {\n        useESM: true,\n        tsconfig: {\n          module: 'esnext'\n        }\n      }\n    ]\n  },\n  transformIgnorePatterns: ['node_modules/(?!(.*\\\\.mjs$))']\n}\n"
  },
  {
    "path": "license",
    "content": "The MIT License (MIT)\n\nCopyright (c) akameco <akameco.t@gmail.com> (akameco.github.io)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"extract-react-intl-messages\",\n  \"version\": \"5.0.0\",\n  \"description\": \"Extract react-intl messages\",\n  \"license\": \"MIT\",\n  \"repository\": \"akameco/extract-react-intl-messages\",\n  \"type\": \"module\",\n  \"author\": {\n    \"name\": \"akameco\",\n    \"email\": \"akameco.t@gmail.com\",\n    \"url\": \"https://akameco.github.io\"\n  },\n  \"engines\": {\n    \"node\": \">=20\"\n  },\n  \"main\": \"dist/index.js\",\n  \"scripts\": {\n    \"fmt\": \"prettier --write .\",\n    \"example\": \"./cli.js -l=en,ja -o example/i18n -d en 'example/**/*.{js,tsx}'\",\n    \"example:yaml\": \"./cli.js -l=en,ja -f=yaml -o example/i18n -d en 'example/**/*.{js,tsx}'\",\n    \"prepublish\": \"npm run build\",\n    \"build\": \"tsc\",\n    \"lint\": \"eslint src/**/*.ts --fix --cache\",\n    \"pretest\": \"node -e \\\"import('fs/promises').then(fs => fs.rm('.test-cache', {recursive: true, force: true})).catch(() => {})\\\"\",\n    \"test\": \"jest\",\n    \"posttest\": \"node -e \\\"import('fs/promises').then(fs => fs.rm('.test-cache', {recursive: true, force: true})).catch(() => {})\\\"\",\n    \"prepare\": \"husky\"\n  },\n  \"bin\": {\n    \"extract-messages\": \"dist/cli.js\",\n    \"extract-react-intl-messages\": \"dist/cli.js\"\n  },\n  \"files\": [\n    \"dist\"\n  ],\n  \"keywords\": [\n    \"react\",\n    \"i18n\",\n    \"intl\",\n    \"react-intl\",\n    \"extract\",\n    \"json\",\n    \"messages\"\n  ],\n  \"dependencies\": {\n    \"@babel/core\": \"^7.28.3\",\n    \"babel-plugin-react-intl\": \"^7.9.4\",\n    \"deepmerge\": \"^4.3.1\",\n    \"file-entry-cache\": \"^5.0.1\",\n    \"flat\": \"^5.0.2\",\n    \"glob\": \"11.0.3\",\n    \"js-yaml\": \"4.1.0\",\n    \"load-json-file\": \"^6.2.0\",\n    \"lodash.merge\": \"^4.6.2\",\n    \"meow\": \"13.2.0\",\n    \"read-babelrc-up\": \"^1.1.0\",\n    \"sort-keys\": \"^4.2.0\",\n    \"write-json-file\": \"^4.3.0\"\n  },\n  \"devDependencies\": {\n    \"@babel/plugin-proposal-class-properties\": \"^7.18.6\",\n    \"@babel/preset-env\": \"^7.28.3\",\n    \"@babel/preset-flow\": \"^7.27.1\",\n    \"@babel/preset-react\": \"^7.27.1\",\n    \"@types/file-entry-cache\": \"^5.0.4\",\n    \"@types/flat\": \"^5.0.5\",\n    \"@types/js-yaml\": \"^3.12.10\",\n    \"@types/load-json-file\": \"^2.0.7\",\n    \"@types/lodash.merge\": \"^4.6.9\",\n    \"@types/node\": \"^24.3.0\",\n    \"@types/temp-write\": \"^4.0.0\",\n    \"@types/write-json-file\": \"^2.2.1\",\n    \"babel-plugin-react-intl-auto\": \"^3.3.0\",\n    \"eslint\": \"^9.34.0\",\n    \"husky\": \"9.1.7\",\n    \"jest\": \"^30.1.1\",\n    \"lint-staged\": \"16.1.5\",\n    \"prettier\": \"3.6.2\",\n    \"temp-write\": \"^4.0.0\",\n    \"tempy\": \"^0.5.0\",\n    \"ts-jest\": \"^29.4.1\",\n    \"typescript\": \"^5.9.2\",\n    \"typescript-eslint\": \"^8.41.0\"\n  },\n  \"lint-staged\": {\n    \"*.ts\": [\n      \"prettier --write\",\n      \"eslint --fix\"\n    ],\n    \"*.{js,json,md}\": [\n      \"prettier --write\"\n    ]\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# extract-react-intl-messages\n\n[![test](https://github.com/akameco/extract-react-intl-messages/workflows/test/badge.svg)](https://github.com/akameco/extract-react-intl-messages/actions?query=workflow%3Atest)\n[![tested with jest](https://img.shields.io/badge/tested_with-jest-99424f.svg)](https://github.com/facebook/jest)\n[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)\n[![MIT License](https://img.shields.io/npm/l/nps.svg?style=flat-square)](./license)\n[![All Contributors](https://img.shields.io/badge/all_contributors-14-orange.svg?style=flat-square)](#contributors-)\n\nThis package will generate json or yaml files from a glob. It will generate one file per locale, with the ids of each message defined by the [`defineMessages`](https://github.com/yahoo/react-intl/wiki/API#definemessages) function of [react-intl](https://github.com/yahoo/react-intl). The value of each of these keys will be an empty string, except for your `defaultLocale` which will be populated with the [`defaultMessage`](https://github.com/yahoo/react-intl/wiki/API#message-descriptor).\n\n## Dependencies\n\n### Babel\n\n- 0.x works with Babel 6\n\n## Install\n\n```\n$ npm install --save-dev extract-react-intl-messages\n```\n\n## Usage\n\napp/components/App/messages.js\n\n```js\nimport { defineMessages, useIntl } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'a.world',\n    defaultMessage: 'world'\n  }\n})\n\nexport const SubmitButton = () => {\n  const intl = useIntl()\n  const label = intl.formatMessage({\n    id: 'a.submit',\n    defaultMessage: 'Submit Button'\n  })\n  return <button aria-label={label}>{label}</button>\n}\n```\n\n### Run Script\n\n```\n$ extract-messages -l=en,ja -o app/translations -d en --flat false './app/**/!(*.test).js'\n```\n\n### Output\n\napp/translations/en.json\n\n```json\n{\n  \"a\": {\n    \"hello\": \"hello\",\n    \"world\": \"world\",\n    \"submit\": \"Submit Button\"\n  }\n}\n```\n\napp/translations/ja.json\n\n```json\n{\n  \"a\": {\n    \"hello\": \"\",\n    \"world\": \"\",\n    \"submit\": \"\"\n  }\n}\n```\n\n## Recommend\n\nUse with [babel-plugin-react-intl-auto: i18n for the component age. Auto management react-intl ID.](https://github.com/akameco/babel-plugin-react-intl-auto)\n\n## CLI\n\n```console\n$ extract-messages --help\n\n  Extract react-intl messages\n\n  Usage\n  $ extract-react-intl-messages <input>\n  $ extract-messages <input>\n\n  Options\n  -o, --output            Output directory [require: true]\n  -l, --locales           locales [require: true]\n  -f, --format            json | yaml [default: json]\n  -d, --defaultLocale     default locale\n  --overwriteDefault      default: true\n  --flat                  json [default: true] | yaml [default: false]\n  --indent                default: 2\n\n  Example\n  $ extract-messages --locales=ja,en --output app/translations 'app/**/*.js'\n  $ extract-messages -l=ja,en -o i18n 'src/**/*.js'\n  $ extract-messages -l=ja,en -o app/translations -f yaml 'app/**/messages.js'\n```\n\n### create-react-app user\n\ncreate `.babelrc` like this.\n\n```json\n{\n  \"presets\": [\"react-app\"]\n}\n```\n\nRun with `NODE_ENV=development`.\n\n```\n$ NODE_ENV=development extract-messages ...\n```\n\n### TypeScript\n\nbabel required.\n\nSee [example/with-typescript](example/with-typescript)\n\n```\nnpm install --save-dev @babel/core @babel/preset-typescript @babel/preset-react\n```\n\n`babel.config.js`\n\n```js\nmodule.exports = function (api) {\n  api.cache(true)\n\n  return {\n    presets: ['@babel/preset-react', '@babel/preset-typescript']\n  }\n}\n```\n\n## API\n\n### extractReactIntlMessages(locales, input, buildDir, [options])\n\n#### locales\n\nType: `Array<string>`\n\nExample: `['en', 'ja']`\n\n#### input\n\nType: `Array<string>`\n\nTarget files.\nglob.\n\n#### buildDir\n\nType: `string`\n\nExport directory.\n\n#### options\n\n##### defaultLocale\n\nType: `string`<br>\nDefault: `en`\n\n##### format\n\nType: `json` | `yaml`<br>\nDefault: `json`\n\nSet extension to output.\n\n##### overwriteDefault\n\nType: `boolean`<br>\nDefault: true\n\nIf overwriteDefault is `false`, it will not overwrite messages in the default locale.\n\n##### indent\n\nType: `number`<br>\nDefault: `2`\n\n##### flat\n\nType: `boolean`<br>\nDefault: `true`\n\nIf format is `yaml`, set to `false`.\n\nBe careful if `false`.\nSee [this issue](https://github.com/akameco/extract-react-intl-messages/issues/3).\n\n##### babel-plugin-react-intl's Options\n\nSee https://github.com/formatjs/formatjs/tree/master/packages/babel-plugin-react-intl#options\n\n## Contributors\n\nThanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):\n\n<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n<!-- prettier-ignore-start -->\n<!-- markdownlint-disable -->\n<table>\n  <tbody>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"http://akameco.github.io\"><img src=\"https://avatars2.githubusercontent.com/u/4002137?v=4?s=100\" width=\"100px;\" alt=\"akameco\"/><br /><sub><b>akameco</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=akameco\" title=\"Code\">💻</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=akameco\" title=\"Tests\">⚠️</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=akameco\" title=\"Documentation\">📖</a> <a href=\"#infra-akameco\" title=\"Infrastructure (Hosting, Build-Tools, etc)\">🚇</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"http://hoantran.info\"><img src=\"https://avatars3.githubusercontent.com/u/13161875?v=4?s=100\" width=\"100px;\" alt=\"Hoan Tran\"/><br /><sub><b>Hoan Tran</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=hoantran-it\" title=\"Code\">💻</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=hoantran-it\" title=\"Tests\">⚠️</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/giantpinkwalrus\"><img src=\"https://avatars1.githubusercontent.com/u/3383240?v=4?s=100\" width=\"100px;\" alt=\"giantpinkwalrus\"/><br /><sub><b>giantpinkwalrus</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=giantpinkwalrus\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/enrique-ramirez\"><img src=\"https://avatars3.githubusercontent.com/u/1190640?v=4?s=100\" width=\"100px;\" alt=\"enrique-ramirez\"/><br /><sub><b>enrique-ramirez</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=enrique-ramirez\" title=\"Documentation\">📖</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"http://stefan-gojan.de\"><img src=\"https://avatars2.githubusercontent.com/u/163128?v=4?s=100\" width=\"100px;\" alt=\"Stefan Gojan\"/><br /><sub><b>Stefan Gojan</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/issues?q=author%3Ahoschi\" title=\"Bug reports\">🐛</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=hoschi\" title=\"Code\">💻</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=hoschi\" title=\"Tests\">⚠️</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://lithe.net\"><img src=\"https://avatars1.githubusercontent.com/u/857744?v=4?s=100\" width=\"100px;\" alt=\"Solomon English\"/><br /><sub><b>Solomon English</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=solomon23\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/Filson14\"><img src=\"https://avatars1.githubusercontent.com/u/4540538?v=4?s=100\" width=\"100px;\" alt=\"Filip &quot;Filson&quot; Pasternak\"/><br /><sub><b>Filip &quot;Filson&quot; Pasternak</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=Filson14\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"http://about.me/nodaguti\"><img src=\"https://avatars0.githubusercontent.com/u/27622?v=4?s=100\" width=\"100px;\" alt=\"nodaguti\"/><br /><sub><b>nodaguti</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=nodaguti\" title=\"Code\">💻</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=nodaguti\" title=\"Tests\">⚠️</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/fix-fix\"><img src=\"https://avatars1.githubusercontent.com/u/11943024?v=4?s=100\" width=\"100px;\" alt=\"fix-fix\"/><br /><sub><b>fix-fix</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=fix-fix\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"http://bradbarrow.com\"><img src=\"https://avatars3.githubusercontent.com/u/1264276?v=4?s=100\" width=\"100px;\" alt=\"bradbarrow\"/><br /><sub><b>bradbarrow</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/issues?q=author%3Abradbarrow\" title=\"Bug reports\">🐛</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=bradbarrow\" title=\"Code\">💻</a> <a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=bradbarrow\" title=\"Tests\">⚠️</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"http://ddem.us/\"><img src=\"https://avatars1.githubusercontent.com/u/290457?v=4?s=100\" width=\"100px;\" alt=\"Gregor MacLennan\"/><br /><sub><b>Gregor MacLennan</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=gmaclennan\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/zarv1k\"><img src=\"https://avatars1.githubusercontent.com/u/6296643?v=4?s=100\" width=\"100px;\" alt=\"Dmitry Zarva\"/><br /><sub><b>Dmitry Zarva</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=zarv1k\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/panpanc\"><img src=\"https://avatars2.githubusercontent.com/u/29132669?v=4?s=100\" width=\"100px;\" alt=\"Michael Pan\"/><br /><sub><b>Michael Pan</b></sub></a><br /><a href=\"#example-panpanc\" title=\"Examples\">💡</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/testower\"><img src=\"https://avatars2.githubusercontent.com/u/231492?v=4?s=100\" width=\"100px;\" alt=\"Tom Erik Støwer\"/><br /><sub><b>Tom Erik Støwer</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=testower\" title=\"Code\">💻</a></td>\n    </tr>\n    <tr>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://nextbook.io\"><img src=\"https://avatars0.githubusercontent.com/u/20876627?v=4?s=100\" width=\"100px;\" alt=\"Bart Lens\"/><br /><sub><b>Bart Lens</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=lensbart\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/revskill10\"><img src=\"https://avatars3.githubusercontent.com/u/1390196?v=4?s=100\" width=\"100px;\" alt=\"Truong Hoang Dung\"/><br /><sub><b>Truong Hoang Dung</b></sub></a><br /><a href=\"#example-revskill10\" title=\"Examples\">💡</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://github.com/Nestoro\"><img src=\"https://avatars.githubusercontent.com/u/13397845?v=4?s=100\" width=\"100px;\" alt=\"Nestoro\"/><br /><sub><b>Nestoro</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=Nestoro\" title=\"Code\">💻</a></td>\n      <td align=\"center\" valign=\"top\" width=\"14.28%\"><a href=\"https://lightnet328.com/\"><img src=\"https://avatars.githubusercontent.com/u/2351326?v=4?s=100\" width=\"100px;\" alt=\"Yutaro Kido\"/><br /><sub><b>Yutaro Kido</b></sub></a><br /><a href=\"https://github.com/akameco/extract-react-intl-messages/commits?author=lightnet328\" title=\"Code\">💻</a></td>\n    </tr>\n  </tbody>\n</table>\n\n<!-- markdownlint-restore -->\n<!-- prettier-ignore-end -->\n\n<!-- ALL-CONTRIBUTORS-LIST:END -->\n\nThis project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!\n\n## License\n\nMIT © [akameco](http://akameco.github.io)\n"
  },
  {
    "path": "src/cli.ts",
    "content": "#!/usr/bin/env node\n \nimport meow from 'meow'\nimport extractMessage from './index.js'\n\nconst cli = meow(\n  `\n  Usage\n  $ extract-react-intl-messages <input>\n  $ extract-messages <input>\n\n  Options\n  -o, --output            Output directory [require: true]\n  -l, --locales           locales [require: true]\n  -f, --format            json | yaml [default: json]\n  -d, --default-locale    default locale\n  --overwriteDefault      [default: true]\n  --flat                  json [default: true] | yaml [default: false]\n  --cache                 [default: false]\n  --cacheLocation         [default: .extract-react-intl-messages-cache]\n  --indent                default: 2\n\n  Example\n  $ extract-messages --locales=ja,en --output app/translations 'app/**/*.js'\n  $ extract-messages -l=ja,en -o app/translations -f yaml 'app/**/messages.js'\n`,\n  {\n    importMeta: import.meta,\n    flags: {\n      flat: {\n        type: 'boolean'\n      },\n      output: {\n        type: 'string',\n        shortFlag: 'o'\n      },\n      locales: {\n        type: 'string',\n        shortFlag: 'l'\n      },\n      format: {\n        type: 'string',\n        shortFlag: 'f',\n        default: 'json'\n      },\n      defaultLocale: {\n        type: 'string',\n        shortFlag: 'd'\n      },\n      overwriteDefault: {\n        type: 'boolean',\n        default: true\n      },\n      withDescriptions: {\n        type: 'boolean',\n        default: false\n      },\n      // babel-plugin-react-intl boolean options\n      extractSourceLocation: {\n        type: 'boolean',\n        default: false\n      },\n      removeDefaultMessage: {\n        type: 'boolean'\n      },\n      extractFromFormatMessageCall: {\n        type: 'boolean',\n        default: true\n      },\n      indent: {\n        type: 'number',\n        default: 2\n      }\n    }\n  }\n)\n\nconst { output, locales } = cli.flags\n\nif (!output) {\n  console.log('ERROR: required output')\n  process.exit(1)\n}\n\nif (!locales || typeof locales !== 'string') {\n  console.log('ERROR: required locales')\n  process.exit(1)\n}\n\nconst localesMap = locales.split(',')\n\n/* eslint-disable-next-line @typescript-eslint/no-explicit-any */\nextractMessage(localesMap, cli.input[0], output, cli.flags as any)\n"
  },
  {
    "path": "src/extract-react-intl/index.ts",
    "content": "import path from 'path'\nimport { glob } from 'glob'\nimport { promisify } from 'util'\nimport merge from 'lodash.merge'\nimport deepmerge from 'deepmerge'\nimport {\n  resolvePlugin,\n  resolvePreset,\n  transformFile,\n  PluginItem\n} from '@babel/core'\nimport readBabelrcUp from 'read-babelrc-up'\nimport babelPluginReactIntl from 'babel-plugin-react-intl'\nimport fileEntryCache, { FileDescriptor } from 'file-entry-cache'\n\ntype LocaleMap = Record<string, Record<string, unknown>>\n\nconst localeMap = (arr: string[]): LocaleMap =>\n  arr.reduce((obj: LocaleMap, x: string) => {\n    obj[x] = {}\n    return obj\n  }, {})\n\nconst createResolveList =\n  (fn: (name: string, dirname: string) => string | null) =>\n  (list: PluginItem[], cwd: string) =>\n    list.map((x) => (typeof x === 'string' ? fn(x, cwd) : x))\n\nconst resolvePresets = createResolveList(resolvePreset)\nconst resolvePlugins = createResolveList(resolvePlugin)\n\nconst getBabelrc = (cwd: string) => {\n  try {\n    const babelrc = readBabelrcUp.sync({ cwd }).babel\n    if (!babelrc.env) {\n      return babelrc\n    }\n\n    const env = process.env.BABEL_ENV || process.env.NODE_ENV || 'development'\n\n    return deepmerge(babelrc, babelrc.env[env] || {})\n  } catch {\n    return { presets: [], plugins: [] }\n  }\n}\n\nconst getBabelrcDir = (cwd: string) =>\n  path.dirname(readBabelrcUp.sync({ cwd }).path)\n\nconst babelPluginReactIntlOptions = new Set([\n  'moduleSourceName',\n  'extractSourceLocation',\n  'messagesDir',\n  'overrideIdFn',\n  'removeDefaultMessage',\n  'extractFromFormatMessageCall',\n  'additionalComponentNames'\n])\n\ntype Options = {\n  [key: string]: unknown\n  defaultLocale?: string\n  cwd?: string\n  cache?: boolean\n  cacheLocation?: string\n  withDescriptions?: boolean\n}\n\ntype Message = {\n  id: string\n  defaultMessage: string\n  description: string\n}\n\ntype CacheData = {\n  defaultLocale: string\n  localeMap: LocaleMap\n}\n\ntype File = FileDescriptor & {\n  meta: {\n    data: CacheData\n  }\n}\n\nexport default async (\n  locales: string[],\n  pattern: string,\n  {\n    defaultLocale = 'en',\n    withDescriptions = false,\n    cwd = process.cwd(),\n    cache: cacheEnabled = false,\n    cacheLocation = '.extract-react-intl-messages-cache',\n    ...pluginOptions\n  }: Options = {}\n) => {\n  if (!Array.isArray(locales)) {\n    throw new TypeError(`Expected a Array, got ${typeof locales}`)\n  }\n\n  if (typeof pattern !== 'string') {\n    throw new TypeError(`Expected a string, got ${typeof pattern}`)\n  }\n\n  const babelrc = getBabelrc(cwd) || {}\n  const babelrcDir = getBabelrcDir(cwd)\n\n  const presets = babelrc.presets || []\n  const plugins = babelrc.plugins || []\n\n  if (\n    !plugins.find(\n      (plugin: PluginItem) =>\n        (Array.isArray(plugin) ? plugin[0] : plugin) === 'react-intl'\n    )\n  ) {\n    // Append a the `react-intl` babel plugin only when it isn’t already included in the babel config\n    presets.unshift({\n      plugins: [\n        [\n          babelPluginReactIntl,\n          Object.entries(pluginOptions).reduce((acc, [key, value]) => {\n            if (babelPluginReactIntlOptions.has(key)) {\n              return { ...acc, [key]: value }\n            }\n            return acc\n          }, {})\n        ]\n      ]\n    })\n  }\n\n  const files: string[] = await glob(pattern)\n  if (files.length === 0) {\n    throw new Error(`File not found (${pattern})`)\n  }\n\n  const cachePath = path.resolve(cacheLocation)\n  const cacheDirname = path.dirname(cachePath)\n  const cacheBasename = path.basename(cachePath)\n\n  const cache = cacheEnabled\n    ? fileEntryCache.create(cacheBasename, cacheDirname)\n    : null\n\n  const extractFromFile = async (file: string) => {\n    const babelOpts = {\n      presets: resolvePresets(presets, babelrcDir),\n      plugins: resolvePlugins(plugins, babelrcDir)\n    }\n    /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n    const transformResult = await promisify(transformFile as any)(\n      file,\n      babelOpts\n    )\n    /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n    const { metadata } = transformResult as { metadata: any }\n    const localeObj = localeMap(locales)\n    const result = metadata['react-intl'].messages as Message[]\n    for (const { id, defaultMessage, description } of result) {\n      for (const locale of locales) {\n        const message = defaultLocale === locale ? defaultMessage : ''\n        localeObj[locale][id] = withDescriptions\n          ? { message, description }\n          : message\n      }\n    }\n    return localeObj\n  }\n\n  const extractFromCache = async (file: string) => {\n    if (cache === null) {\n      return extractFromFile(file)\n    }\n\n    const cachedLocaleObj = cache?.getFileDescriptor(file) as File | undefined\n    const changed = cachedLocaleObj?.changed\n    const data = cachedLocaleObj?.meta.data\n\n    if (changed === false && data?.defaultLocale === defaultLocale) {\n      return data.localeMap\n    }\n\n    const localeObj = await extractFromFile(file)\n\n    if (cachedLocaleObj) {\n      cachedLocaleObj.meta.data = { defaultLocale, localeMap: localeObj }\n    }\n\n    return localeObj\n  }\n\n  const extract = cacheEnabled ? extractFromCache : extractFromFile\n\n  const arr = await Promise.all(files.map(extract))\n\n  if (cache) {\n    cache.reconcile()\n  }\n\n  return arr.reduce((h, obj) => merge(h, obj), localeMap(locales))\n}\n"
  },
  {
    "path": "src/extract-react-intl/readme.md",
    "content": "# extract-react-intl\n\n## API\n\n### extractReactIntl(locales, pattern, [options])\n\nReturn a `Promise` wrapped extracted messages.\n\n#### locales\n\nType: `Array<string>`\n\nExample: `['en', 'ja']`\n\n#### pattern\n\nType: `string`\n\nFile path with glob.\n\n#### options\n\nAdditional options.\n\n#### defaultLocale\n\nType: `string`<br> Default: `en`\n\nSet default locale for your app.\n\n##### cwd\n\nType: `string`<br> Default: `.`\n\n**You most likely don't need this.**\n\nChange run path.\n"
  },
  {
    "path": "src/extract-react-intl/test/__snapshots__/test.ts.snap",
    "content": "// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing\n\nexports[`babel plugin execution order 1`] = `\n{\n  \"en\": {\n    \"src.extract-react-intl.test.pluginOrdering.test\": \"auto\",\n  },\n}\n`;\n\nexports[`extract from file 1`] = `\n{\n  \"en\": {\n    \"components.App.1248161314\": \"Submit button\",\n    \"components.App.hello\": \"hello\",\n    \"components.App.world\": \"world\",\n    \"components/Greeting/welcome\": \"\n    Welcome {name}, you have received {unreadCount, plural,\n      =0 {no new messages}\n      one {{formattedUnreadCount} new message}\n      other {{formattedUnreadCount} new messages}\n    } since {formattedLastLoginTime}.\n    \",\n  },\n  \"ja\": {\n    \"components.App.1248161314\": \"\",\n    \"components.App.hello\": \"\",\n    \"components.App.world\": \"\",\n    \"components/Greeting/welcome\": \"\",\n  },\n}\n`;\n\nexports[`extract from file by enabling cache and extract from cache 1`] = `\n{\n  \"en\": {\n    \"components.App.1248161314\": \"Submit button\",\n    \"components.App.hello\": \"hello\",\n    \"components.App.world\": \"world\",\n    \"components/Greeting/welcome\": \"\n    Welcome {name}, you have received {unreadCount, plural,\n      =0 {no new messages}\n      one {{formattedUnreadCount} new message}\n      other {{formattedUnreadCount} new messages}\n    } since {formattedLastLoginTime}.\n    \",\n  },\n  \"ja\": {\n    \"components.App.1248161314\": \"\",\n    \"components.App.hello\": \"\",\n    \"components.App.world\": \"\",\n    \"components/Greeting/welcome\": \"\",\n  },\n}\n`;\n\nexports[`extract from file by enabling cache and extract from cache 2`] = `\n{\n  \"en\": {\n    \"components.App.1248161314\": \"Submit button\",\n    \"components.App.hello\": \"hello\",\n    \"components.App.world\": \"world\",\n    \"components/Greeting/welcome\": \"\n    Welcome {name}, you have received {unreadCount, plural,\n      =0 {no new messages}\n      one {{formattedUnreadCount} new message}\n      other {{formattedUnreadCount} new messages}\n    } since {formattedLastLoginTime}.\n    \",\n  },\n  \"ja\": {\n    \"components.App.1248161314\": \"\",\n    \"components.App.hello\": \"\",\n    \"components.App.world\": \"\",\n    \"components/Greeting/welcome\": \"\",\n  },\n}\n`;\n\nexports[`extract from file with descriptions 1`] = `\n{\n  \"en\": {\n    \"components.App.hello\": {\n      \"description\": \"hello message description\",\n      \"message\": \"hello\",\n    },\n    \"components.App.world\": {\n      \"description\": \"world message description\",\n      \"message\": \"world\",\n    },\n    \"components/Greeting/welcome\": {\n      \"description\": \"Welcome message description\",\n      \"message\": \"\n    Welcome {name}, you have received {unreadCount, plural,\n      =0 {no new messages}\n      one {{formattedUnreadCount} new message}\n      other {{formattedUnreadCount} new messages}\n    } since {formattedLastLoginTime}.\n    \",\n    },\n  },\n  \"ja\": {\n    \"components.App.hello\": {\n      \"description\": \"hello message description\",\n      \"message\": \"\",\n    },\n    \"components.App.world\": {\n      \"description\": \"world message description\",\n      \"message\": \"\",\n    },\n    \"components/Greeting/welcome\": {\n      \"description\": \"Welcome message description\",\n      \"message\": \"\",\n    },\n  },\n}\n`;\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/.babelrc",
    "content": "{\n  \"presets\": [\n    [\n      \"@babel/preset-env\",\n      {\n        \"targets\": {\n          \"browsers\": [\n            \"last 2 versions\",\n            \"safari >= 7\"\n          ]\n        }\n      }\n    ],\n    \"@babel/preset-react\",\n    \"@babel/preset-flow\"\n  ],\n  \"plugins\": [\n    \"@babel/plugin-proposal-class-properties\"\n  ],\n  \"env\": {\n    \"react-intl\": {\n      \"plugins\": [\n        [\n          \"react-intl-auto\",\n          {\n            \"removePrefix\": \"src.extract-react-intl.test.fixtures\"\n          }\n        ]\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/components/App/index.js",
    "content": "// @flow\nimport React, { Component } from 'react'\nimport { FormattedMessage, injectIntl } from 'react-intl'\nimport Greeting from '../Greeting'\nimport messages from './messages'\n\ninjectIntl(({ intl }) => {\n  const label = intl.formatMessage({ defaultMessage: \"Submit button\" })\n\n  return <button aria-label={label}>{label}</button>\n});\n\n\nexport default class App extends Component {\n  render() {\n    const user = {\n      name: 'Eric',\n      unreadCount: 4,\n      lastLoginTime: Date.now() - 1000 * 60 * 60 * 24\n    }\n\n    return (\n      <div>\n        <FormattedMessage {...messages.hello} />\n        <Greeting user={user} />\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/components/App/messages.js",
    "content": "// @flow\nimport { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  // hello message description\n  hello: 'hello',\n  // world message description\n  world: 'world'\n})\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/components/Greeting/index.js",
    "content": "// @flow\nimport React, { Component } from 'react'\nimport {\n  FormattedMessage,\n  FormattedNumber,\n  FormattedRelative\n} from 'react-intl'\nimport messages from './messages'\n\ntype Props = {\n  user: {\n    name: string,\n    unreadCount: number,\n    lastLoginTime: number\n  }\n}\n\nexport default class Greeting extends Component {\n  props: Props\n\n  render() {\n    const { user } = this.props\n\n    return (\n      <p>\n        <FormattedMessage\n          {...messages.welcome}\n          values={{\n            name: <b>{user.name}</b>,\n            unreadCount: user.unreadCount,\n            formattedUnreadCount: (\n              <b>\n                <FormattedNumber value={user.unreadCount} />\n              </b>\n            ),\n            formattedLastLoginTime: (\n              <FormattedRelative value={user.lastLoginTime} />\n            )\n          }}\n        />\n      </p>\n    )\n  }\n}\n\nfunction defaultMessage() {\n  return 'hello'\n}\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/components/Greeting/messages.js",
    "content": "// @flow\nimport { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  // Welcome message description\n  welcome: {\n    id: 'components/Greeting/welcome',\n    defaultMessage: `\n    Welcome {name}, you have received {unreadCount, plural,\n      =0 {no new messages}\n      one {{formattedUnreadCount} new message}\n      other {{formattedUnreadCount} new messages}\n    } since {formattedLastLoginTime}.\n    `\n  }\n})\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/components/LanguageProvider/index.js",
    "content": "// @flow\nimport React, { Component } from 'react'\nimport { addLocaleData, IntlProvider } from 'react-intl'\nimport enLocaleData from 'react-intl/locale-data/en'\nimport jaLocaleData from 'react-intl/locale-data/ja'\n\nimport enMessages from '../../translations/en.json'\nimport jaMessages from '../../translations/ja.json'\n\naddLocaleData(enLocaleData)\naddLocaleData(jaLocaleData)\n\nconst messages = {\n  en: enMessages,\n  ja: jaMessages\n}\n\nexport default class LanguageProvider extends Component {\n  props: { children?: React$Element<*> }\n  state: { locale: string } = { locale: 'en' }\n\n  render() {\n    const { locale } = this.state\n    return (\n      <div>\n        <IntlProvider locale={locale} messages={messages[locale]}>\n          {this.props.children}\n        </IntlProvider>\n        <a onClick={() => this.setState({ locale: 'en' })}>English</a>\n        /\n        <a onClick={() => this.setState({ locale: 'ja' })}>日本語</a>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n      <title>Example</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script src=\"/assets/bundle.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "src/extract-react-intl/test/fixtures/index.js",
    "content": "// @flow\nimport React from 'react'\nimport ReactDOM from 'react-dom'\nimport App from './components/App'\nimport LanguageProvider from './components/LanguageProvider'\n\nReactDOM.render(\n  <LanguageProvider>\n    <App />\n  </LanguageProvider>,\n  document.getElementById('root')\n)\n"
  },
  {
    "path": "src/extract-react-intl/test/pluginOrdering/.babelrc",
    "content": "{\n  \"presets\": [\"@babel/preset-flow\"],\n  \"plugins\": [\"react-intl-auto\"]\n}\n"
  },
  {
    "path": "src/extract-react-intl/test/pluginOrdering/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  test: 'auto'\n})\n"
  },
  {
    "path": "src/extract-react-intl/test/resolution/.babelrc",
    "content": "{\n  \"presets\": [\"@babel/preset-flow\"],\n  \"plugins\": [\"react-intl\"]\n}\n"
  },
  {
    "path": "src/extract-react-intl/test/resolution/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  test: {\n    id: 'test',\n    defaultMessage: 'test'\n  }\n})\n"
  },
  {
    "path": "src/extract-react-intl/test/test.ts",
    "content": "import m from '..'\n\nconst pattern = 'src/extract-react-intl/test/fixtures/**/*.js'\nconst locales = ['en', 'ja']\n\ntest('extract from file', async () => {\n  process.env.BABEL_ENV = 'react-intl'\n  const x = await m(locales, pattern, {\n    defaultLocale: 'en',\n    cwd: `${__dirname}/fixtures`,\n    extractFromFormatMessageCall: true\n  })\n  expect(x).toMatchSnapshot()\n})\n\ntest('extract from file by enabling cache and extract from cache', async () => {\n  process.env.BABEL_ENV = 'react-intl'\n  const x = await m(locales, pattern, {\n    defaultLocale: 'en',\n    cwd: `${__dirname}/fixtures`,\n    extractFromFormatMessageCall: true,\n    cache: true,\n    cacheLocation: '.test-cache'\n  })\n  expect(x).toMatchSnapshot()\n\n  const y = await m(locales, pattern, {\n    defaultLocale: 'en',\n    cwd: `${__dirname}/fixtures`,\n    extractFromFormatMessageCall: true,\n    cache: true,\n    cacheLocation: '.test-cache'\n  })\n  expect(y).toMatchSnapshot()\n})\n\n// TODO: fix\ntest.skip('babelrc path resolution', async () => {\n  const x = await m(['en'], './extract-react-intl/test/resolution/**/*.js', {\n    defaultLocale: 'en',\n    cwd: `${__dirname}/resolution`\n  })\n  expect(x).toMatchSnapshot()\n})\n\ntest('babel plugin execution order', async () => {\n  const x = await m(\n    ['en'],\n    'src/extract-react-intl/test/pluginOrdering/**/*.js',\n    { defaultLocale: 'en', cwd: `${__dirname}/pluginOrdering` }\n  )\n  expect(x).toMatchSnapshot()\n})\n\ntest('error', async () => {\n  expect.assertions(1)\n  await m(locales, 'notfound', {\n    defaultLocale: 'en',\n    cwd: `${__dirname}/fixtures`\n  }).catch((error) => {\n    expect(error.message).toMatch('File not found')\n  })\n})\n\ntest('extract from file with descriptions', async () => {\n  process.env.BABEL_ENV = 'react-intl'\n  const x = await m(locales, pattern, {\n    defaultLocale: 'en',\n    cwd: './test/fixtures',\n    withDescriptions: true\n  })\n  expect(x).toMatchSnapshot()\n})\n"
  },
  {
    "path": "src/global.d.ts",
    "content": "declare module 'read-babelrc-up' {\n  function sync(opts: { cwd: string }): {\n    path: string\n    babel: import('@babel/core').TransformOptions\n  }\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "import path from 'path'\nimport fs from 'fs'\nimport yaml from 'js-yaml'\nimport { promisify } from 'util'\nimport { flatten, unflatten } from 'flat'\nimport loadJsonFile from 'load-json-file'\nimport writeJsonFile from 'write-json-file'\nimport sortKeys from 'sort-keys'\nimport _extractReactIntl from './extract-react-intl/index.js'\n\nconst writeJson = (outputPath: string, obj: object, indent: number) => {\n  return writeJsonFile(`${outputPath}.json`, obj, { indent })\n}\n\nconst writeYaml = (outputPath: string, obj: object, indent: number) => {\n  return promisify(fs.writeFile)(\n    `${outputPath}.yml`,\n    yaml.dump(obj, { indent }),\n    'utf8'\n  )\n}\n\nconst isJson = (ext: string) => ext === 'json'\n\nfunction loadLocaleFiles(locales: string[], buildDir: string, ext: string) {\n  const oldLocaleMaps: Record<string, Record<string, object>> = {}\n\n  try {\n    fs.mkdirSync(buildDir, { recursive: true })\n  } catch {\n    // Directory already exists or other error, continue\n  }\n\n  for (const locale of locales) {\n    const file = path.resolve(buildDir, `${locale}.${ext}`)\n    // Initialize json file\n    try {\n      const output = isJson(ext) ? JSON.stringify({}) : yaml.dump({})\n      fs.writeFileSync(file, output, { flag: 'wx' })\n    } catch (error: unknown) {\n      if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n        throw error\n      }\n    }\n\n    let messages = isJson(ext)\n      ? loadJsonFile.sync(file)\n      : yaml.load(fs.readFileSync(file, 'utf8'), { json: true })\n\n    messages = flatten(messages)\n\n    oldLocaleMaps[locale] = {}\n    for (const messageKey of Object.keys(messages as object)) {\n      const message = (messages as Record<string, unknown>)[messageKey]\n      if (message && typeof message === 'string' && message !== '') {\n        oldLocaleMaps[locale][messageKey] = (\n          messages as Record<string, unknown>\n        )[messageKey] as object\n      }\n    }\n  }\n\n  return oldLocaleMaps\n}\n\ntype Opts = {\n  [key: string]: unknown\n  defaultLocale: string\n  format?: string\n  flat?: boolean\n  overwriteDefault?: boolean\n  indent?: number\n}\n\nconst extractMessage = async (\n  locales: string[],\n  pattern: string,\n  buildDir: string,\n  {\n    format = 'json',\n    flat = isJson(format),\n    defaultLocale = 'en',\n    overwriteDefault = true,\n    indent = 2,\n    ...opts\n  }: Opts = {\n    defaultLocale: 'en'\n  }\n) => {\n  if (!Array.isArray(locales)) {\n    throw new TypeError(`Expected a Array, got ${typeof locales}`)\n  }\n\n  if (typeof pattern !== 'string') {\n    throw new TypeError(`Expected a string, got ${typeof pattern}`)\n  }\n\n  if (typeof buildDir !== 'string') {\n    throw new TypeError(`Expected a string, got ${typeof buildDir}`)\n  }\n\n  const ext = isJson(format) ? 'json' : 'yml'\n\n  const oldLocaleMaps = loadLocaleFiles(locales, buildDir, ext)\n\n  const extractorOptions = {\n    defaultLocale,\n    withDescriptions: false,\n    cwd: process.cwd(),\n    extractFromFormatMessageCall: true,\n    ...opts\n  }\n\n  const newLocaleMaps = await _extractReactIntl(\n    locales,\n    pattern,\n    extractorOptions\n  )\n\n  return Promise.all(\n    locales.map((locale) => {\n      // If the default locale, overwrite the origin file\n      let localeMap =\n        locale === defaultLocale && overwriteDefault\n          ? // Create a clone so we can use only current valid messages below\n            { ...oldLocaleMaps[locale], ...newLocaleMaps[locale] }\n          : { ...newLocaleMaps[locale], ...oldLocaleMaps[locale] }\n      // Only keep existing keys\n      localeMap = Object.fromEntries(\n        Object.entries(localeMap).filter(([key]) =>\n          Object.keys(newLocaleMaps[locale]).includes(key)\n        )\n      )\n\n      const fomattedLocaleMap: object = flat\n        ? sortKeys(localeMap, { deep: true })\n        : sortKeys(unflatten(localeMap, { object: true }), { deep: true })\n\n      const fn = isJson(format) ? writeJson : writeYaml\n\n      return fn(path.resolve(buildDir, locale), fomattedLocaleMap, indent)\n    })\n  )\n}\n\nextractMessage.extractReactIntl = _extractReactIntl\n\nexport default extractMessage\n"
  },
  {
    "path": "src/test/fixtures/custom/a/messages.js",
    "content": "import { defineMessages } from '../i18n'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.custom.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'a.custom.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/custom/b/messages.js",
    "content": "import { defineMessages } from '../i18n'\n\nexport default defineMessages({\n  hello: {\n    id: 'b.custom.message',\n    defaultMessage: 'Message'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/custom/i18n.js",
    "content": "export { defineMessages } from 'react-intl'\n"
  },
  {
    "path": "src/test/fixtures/default/a/App.js",
    "content": "import React from 'react'\nimport { useIntl } from 'react-intl'\n\nexport const SubmitButton = () => {\n  const intl = useIntl()\n  const label = intl.formatMessage({\n    id: 'a.submit',\n    defaultMessage: 'Submit Button'\n  })\n  return <button aria-label={label}>{label}</button>\n}\n"
  },
  {
    "path": "src/test/fixtures/default/a/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'a.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/default/b/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'b.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'b.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/removed/a/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.hello',\n    defaultMessage: 'hello'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/removed/b/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'b.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'b.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/unsorted/a/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'a.hello',\n    defaultMessage: 'hello'\n  },\n  helloZ: {\n    id: 'z.hello',\n    defaultMessage: 'hello'\n  },\n  helloC: {\n    id: 'c.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'a.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "src/test/fixtures/unsorted/b/messages.js",
    "content": "import { defineMessages } from 'react-intl'\n\nexport default defineMessages({\n  hello: {\n    id: 'b.hello',\n    defaultMessage: 'hello'\n  },\n  helloY: {\n    id: 'y.hello',\n    defaultMessage: 'hello'\n  },\n  world: {\n    id: 'b.world',\n    defaultMessage: 'world'\n  }\n})\n"
  },
  {
    "path": "src/test/json/__snapshots__/test.ts.snap",
    "content": "// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing\n\nexports[`export json - nest 1`] = `\n{\n  \"a\": {\n    \"hello\": \"hello\",\n    \"submit\": \"Submit Button\",\n    \"world\": \"world\",\n  },\n  \"b\": {\n    \"hello\": \"hello\",\n    \"world\": \"world\",\n  },\n}\n`;\n\nexports[`export json - nest 2`] = `\n{\n  \"a\": {\n    \"hello\": \"\",\n    \"submit\": \"\",\n    \"world\": \"\",\n  },\n  \"b\": {\n    \"hello\": \"\",\n    \"world\": \"\",\n  },\n}\n`;\n\nexports[`export json 1`] = `\n{\n  \"a.hello\": \"hello\",\n  \"a.submit\": \"Submit Button\",\n  \"a.world\": \"world\",\n  \"b.hello\": \"hello\",\n  \"b.world\": \"world\",\n}\n`;\n\nexports[`export json 2`] = `\n{\n  \"a.hello\": \"\",\n  \"a.submit\": \"\",\n  \"a.world\": \"\",\n  \"b.hello\": \"\",\n  \"b.world\": \"\",\n}\n`;\n\nexports[`export json with removed messages 1`] = `\n{\n  \"a.hello\": \"hello\",\n  \"a.submit\": \"Submit Button\",\n  \"a.world\": \"world\",\n  \"b.hello\": \"hello\",\n  \"b.world\": \"world\",\n}\n`;\n\nexports[`export json with removed messages 2`] = `\n{\n  \"a.hello\": \"\",\n  \"a.submit\": \"\",\n  \"a.world\": \"\",\n  \"b.hello\": \"\",\n  \"b.world\": \"\",\n}\n`;\n\nexports[`export json with removed messages 3`] = `\n{\n  \"a.hello\": \"hello\",\n  \"b.hello\": \"hello\",\n  \"b.world\": \"world\",\n}\n`;\n\nexports[`export json with removed messages 4`] = `\n{\n  \"a.hello\": \"\",\n  \"b.hello\": \"\",\n  \"b.world\": \"\",\n}\n`;\n\nexports[`export using custom module 1`] = `\n{\n  \"a.custom.hello\": \"hello\",\n  \"a.custom.world\": \"world\",\n  \"b.custom.message\": \"Message\",\n}\n`;\n\nexports[`export using custom module 2`] = `\n{\n  \"a.custom.hello\": \"\",\n  \"a.custom.world\": \"\",\n  \"b.custom.message\": \"\",\n}\n`;\n\nexports[`sort keys 1`] = `\n[\n  \"a.hello\",\n  \"a.world\",\n  \"b.hello\",\n  \"b.world\",\n  \"c.hello\",\n  \"y.hello\",\n  \"z.hello\",\n]\n`;\n\nexports[`sort keys 2`] = `\n[\n  \"a.hello\",\n  \"a.world\",\n  \"b.hello\",\n  \"b.world\",\n  \"c.hello\",\n  \"y.hello\",\n  \"z.hello\",\n]\n`;\n\nexports[`with overwriteDefault 1`] = `\n{\n  \"a.custom.hello\": \"hello\",\n  \"a.custom.world\": \"world\",\n  \"b.custom.message\": \"Default Message\",\n}\n`;\n\nexports[`with overwriteDefault 2`] = `\n{\n  \"a.custom.hello\": \"\",\n  \"a.custom.world\": \"\",\n  \"b.custom.message\": \"\",\n}\n`;\n"
  },
  {
    "path": "src/test/json/test.ts",
    "content": "import fs from 'fs'\nimport path from 'path'\nimport tempy from 'tempy'\nimport m from '../..'\n\ntest('export json', async () => {\n  const tmp = tempy.directory()\n  await m(['en', 'ja'], 'src/test/fixtures/default/**/*.js', tmp)\n  const en = JSON.parse(fs.readFileSync(path.resolve(tmp, 'en.json'), 'utf8'))\n  const ja = JSON.parse(fs.readFileSync(path.resolve(tmp, 'ja.json'), 'utf8'))\n  expect(en).toMatchSnapshot()\n  expect(ja).toMatchSnapshot()\n})\n\ntest('export json with removed messages', async () => {\n  const tmp = tempy.directory()\n  await m(['en', 'ja'], 'src/test/fixtures/default/**/*.js', tmp)\n  const enBefore = JSON.parse(\n    fs.readFileSync(path.resolve(tmp, 'en.json'), 'utf8')\n  )\n  const jaBefore = JSON.parse(\n    fs.readFileSync(path.resolve(tmp, 'ja.json'), 'utf8')\n  )\n  expect(enBefore).toMatchSnapshot()\n  expect(jaBefore).toMatchSnapshot()\n  await m(['en', 'ja'], 'src/test/fixtures/removed/**/*.js', tmp)\n  const en = JSON.parse(fs.readFileSync(path.resolve(tmp, 'en.json'), 'utf8'))\n  const ja = JSON.parse(fs.readFileSync(path.resolve(tmp, 'ja.json'), 'utf8'))\n  expect(en).toMatchSnapshot()\n  expect(ja).toMatchSnapshot()\n})\n\ntest('export json - nest', async () => {\n  const tmp = tempy.directory()\n  await m(['en', 'ja'], 'src/test/fixtures/default/**/*.js', tmp, {\n    defaultLocale: 'en',\n    flat: false\n  })\n  const en = JSON.parse(fs.readFileSync(path.resolve(tmp, 'en.json'), 'utf8'))\n  const ja = JSON.parse(fs.readFileSync(path.resolve(tmp, 'ja.json'), 'utf8'))\n  expect(en).toMatchSnapshot()\n  expect(ja).toMatchSnapshot()\n})\n\ntest('sort keys', async () => {\n  const tmp = tempy.directory()\n  const enPath = path.resolve(tmp, 'en.json')\n  const jaPath = path.resolve(tmp, 'ja.json')\n\n  await m(['en', 'ja'], 'src/test/fixtures/unsorted/**/*.js', tmp)\n  const en = JSON.parse(fs.readFileSync(enPath, 'utf8'))\n  const ja = JSON.parse(fs.readFileSync(jaPath, 'utf8'))\n\n  expect(Object.keys(en)).toMatchSnapshot()\n  expect(Object.keys(ja)).toMatchSnapshot()\n})\n\ntest('export using custom module', async () => {\n  const tmp = tempy.directory()\n  await m(['en', 'ja'], 'src/test/fixtures/custom/**/*.js', tmp, {\n    defaultLocale: 'en',\n    moduleSourceName: '../i18n'\n  })\n  const en = JSON.parse(fs.readFileSync(path.resolve(tmp, 'en.json'), 'utf8'))\n  const ja = JSON.parse(fs.readFileSync(path.resolve(tmp, 'ja.json'), 'utf8'))\n  expect(en).toMatchSnapshot()\n  expect(ja).toMatchSnapshot()\n})\n\ntest('with overwriteDefault', async () => {\n  const tmp = tempy.directory()\n  fs.writeFileSync(\n    path.resolve(tmp, 'en.json'),\n    JSON.stringify(\n      {\n        'a.custom.hello': 'hello',\n        'a.custom.world': 'world',\n        'b.custom.message': 'Default Message'\n      },\n      null,\n      2\n    ),\n    'utf8'\n  )\n  await m(['en', 'ja'], 'src/test/fixtures/custom/**/*.js', tmp, {\n    defaultLocale: 'en',\n    moduleSourceName: '../i18n',\n    overwriteDefault: false\n  })\n  const en = JSON.parse(fs.readFileSync(path.resolve(tmp, 'en.json'), 'utf8'))\n  const ja = JSON.parse(fs.readFileSync(path.resolve(tmp, 'ja.json'), 'utf8'))\n  expect(en).toMatchSnapshot()\n  expect(ja).toMatchSnapshot()\n})\n"
  },
  {
    "path": "src/test/test.ts",
    "content": "import m from '..'\n\ntest('errors', async () => {\n  // @ts-expect-error testing invalid argument type\n  await expect(m('hello')).rejects.toThrow('Expected a Array')\n  // @ts-expect-error testing invalid argument type\n  await expect(m(['en', 'ja'], 2)).rejects.toThrow('Expected a string')\n  // @ts-expect-error testing invalid argument type\n  await expect(m(['en', 'ja'], 'app/', 2)).rejects.toThrow('Expected a string')\n})\n"
  },
  {
    "path": "src/test/yaml/__snapshots__/test.ts.snap",
    "content": "// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing\n\nexports[`export yaml - flat 1`] = `\n{\n  \"a.hello\": \"hello\",\n  \"a.submit\": \"Submit Button\",\n  \"a.world\": \"world\",\n  \"b.hello\": \"hello\",\n  \"b.world\": \"world\",\n}\n`;\n\nexports[`export yaml - flat 2`] = `\n{\n  \"a.hello\": \"\",\n  \"a.submit\": \"\",\n  \"a.world\": \"\",\n  \"b.hello\": \"\",\n  \"b.world\": \"\",\n}\n`;\n\nexports[`export yaml 1`] = `\n{\n  \"a\": {\n    \"hello\": \"hello\",\n    \"submit\": \"Submit Button\",\n    \"world\": \"world\",\n  },\n  \"b\": {\n    \"hello\": \"hello\",\n    \"world\": \"world\",\n  },\n}\n`;\n\nexports[`export yaml 2`] = `\n{\n  \"a\": {\n    \"hello\": \"\",\n    \"submit\": \"\",\n    \"world\": \"\",\n  },\n  \"b\": {\n    \"hello\": \"\",\n    \"world\": \"\",\n  },\n}\n`;\n\nexports[`exsit yaml 1`] = `\n{\n  \"a\": {\n    \"hello\": \"hello\",\n    \"submit\": \"Submit Button\",\n    \"world\": \"world\",\n  },\n  \"b\": {\n    \"hello\": \"hello\",\n    \"world\": \"world\",\n  },\n}\n`;\n\nexports[`exsit yaml 2`] = `\n{\n  \"a\": {\n    \"hello\": \"hello2\",\n    \"submit\": \"\",\n    \"world\": \"\",\n  },\n  \"b\": {\n    \"hello\": \"\",\n    \"world\": \"\",\n  },\n}\n`;\n"
  },
  {
    "path": "src/test/yaml/test.ts",
    "content": "import fs from 'fs'\nimport path from 'path'\nimport tempy from 'tempy'\nimport tempWrite from 'temp-write'\nimport yaml from 'js-yaml'\nimport m from '../..'\n\nconst fixturesPath = 'src/test/fixtures/default/**/*.js'\n\nconst yamlLoad = (tmp: string, file = '') =>\n  yaml.load(fs.readFileSync(path.resolve(tmp, file), 'utf8'))\n\nconst defaultLocale = 'en'\n\ntest('export yaml', async () => {\n  const tmp = tempy.directory()\n  await m(['en', 'ja'], fixturesPath, tmp, { defaultLocale, format: 'yaml' })\n\n  expect(yamlLoad(tmp, 'en.yml')).toMatchSnapshot()\n  expect(yamlLoad(tmp, 'ja.yml')).toMatchSnapshot()\n})\n\ntest('export yaml - flat', async () => {\n  const tmp = tempy.directory()\n  await m(['en', 'ja'], fixturesPath, tmp, {\n    defaultLocale,\n    format: 'yaml',\n    flat: true\n  })\n\n  expect(yamlLoad(tmp, 'en.yml')).toMatchSnapshot()\n  expect(yamlLoad(tmp, 'ja.yml')).toMatchSnapshot()\n})\n\ntest('exsit yaml', async () => {\n  const x = { a: { hello: 'hello2' } }\n\n  const tmpEn = tempWrite.sync(yaml.dump(x), 'en.yml')\n  await m(['en'], fixturesPath, path.dirname(tmpEn), {\n    defaultLocale,\n    format: 'yaml'\n  })\n  expect(yaml.load(fs.readFileSync(tmpEn, 'utf8'))).toMatchSnapshot()\n\n  const tmpJa = tempWrite.sync(yaml.dump(x), 'ja.yml')\n  await m(['ja'], fixturesPath, path.dirname(tmpJa), {\n    defaultLocale,\n    format: 'yaml'\n  })\n\n  expect(yaml.load(fs.readFileSync(tmpJa, 'utf8'))).toMatchSnapshot()\n})\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    /* Language and Environment */\n    \"target\": \"ES2022\",\n    \"lib\": [\"ES2022\", \"DOM\"],\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n\n    /* Modules */\n    \"allowImportingTsExtensions\": false,\n    \"resolveJsonModule\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"isolatedModules\": true,\n\n    /* Emit */\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"dist\",\n    \"removeComments\": false,\n    \"importHelpers\": false,\n    \"downlevelIteration\": false,\n\n    /* Interop Constraints */\n    \"allowJs\": false,\n    \"checkJs\": false,\n\n    /* Type Checking */\n    \"strict\": true,\n    \"noImplicitAny\": true,\n    \"strictNullChecks\": true,\n    \"strictFunctionTypes\": true,\n    \"strictBindCallApply\": true,\n    \"strictPropertyInitialization\": true,\n    \"noImplicitThis\": true,\n    \"useUnknownInCatchVariables\": true,\n    \"alwaysStrict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"exactOptionalPropertyTypes\": false,\n    \"noImplicitReturns\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"noUncheckedIndexedAccess\": false,\n    \"noImplicitOverride\": true,\n    \"noPropertyAccessFromIndexSignature\": false,\n\n    /* Completeness */\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\n    \"node_modules\",\n    \"dist\",\n    \"**/*.test.ts\",\n    \"**/*.spec.ts\",\n    \"**/test.*\"\n  ]\n}\n"
  }
]