├── .all-contributorsrc ├── .eslintignore ├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── nodejs.yml ├── .gitignore ├── .gitmodules ├── .nycrc ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── api-extractor.json ├── karma.conf-ci.js ├── karma.conf.js ├── lerna.json ├── mocha.opts ├── package.json ├── packages ├── babel-plugin-react-intl │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── babel.config.js │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── options.schema.json │ │ └── options.ts │ ├── test │ │ ├── __snapshots__ │ │ │ └── index.test.ts.snap │ │ ├── fixtures │ │ │ ├── FormattedMessage │ │ │ │ └── actual.js │ │ │ ├── additionalComponentNames │ │ │ │ └── actual.js │ │ │ ├── defineMessage │ │ │ │ └── actual.js │ │ │ ├── defineMessages │ │ │ │ └── actual.js │ │ │ ├── descriptionsAsObjects │ │ │ │ └── actual.js │ │ │ ├── empty │ │ │ │ └── actual.js │ │ │ ├── enforceDefaultMessage │ │ │ │ └── actual.js │ │ │ ├── enforceDescriptions │ │ │ │ └── actual.js │ │ │ ├── extractFromFormatMessageCall │ │ │ │ └── actual.js │ │ │ ├── extractFromFormatMessageCallStateless │ │ │ │ └── actual.js │ │ │ ├── extractSourceLocation │ │ │ │ └── actual.js │ │ │ ├── formatMessageCall │ │ │ │ └── actual.js │ │ │ ├── icuSyntax │ │ │ │ └── actual.js │ │ │ ├── inline │ │ │ │ └── actual.js │ │ │ ├── moduleSourceName │ │ │ │ └── actual.js │ │ │ ├── outputEmptyJson │ │ │ │ └── actual.js │ │ │ ├── overrideIdFn │ │ │ │ └── actual.js │ │ │ ├── removeDefaultMessage │ │ │ │ └── actual.js │ │ │ └── removeDescriptions │ │ │ │ └── actual.js │ │ └── index.test.ts │ └── tsconfig.json ├── cli │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── bin │ │ └── formatjs │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── cli.ts │ │ ├── console_utils.ts │ │ ├── extract.ts │ │ └── index.ts │ ├── tests │ │ └── extract │ │ │ ├── integration_tests │ │ │ ├── .gitignore │ │ │ ├── __snapshots__ │ │ │ │ └── index.test.ts.snap │ │ │ ├── defineMessages │ │ │ │ ├── actual.ignore.js │ │ │ │ ├── actual.js │ │ │ │ └── actual.json │ │ │ ├── index.test.ts │ │ │ └── typescript │ │ │ │ ├── actual.ignore.tsx │ │ │ │ ├── actual.json │ │ │ │ └── actual.tsx │ │ │ └── unit.test.ts │ ├── tsconfig.jest.json │ └── tsconfig.json ├── eslint-plugin-formatjs │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── rules │ │ │ ├── blacklist-elements.ts │ │ │ ├── enforce-default-message.ts │ │ │ ├── enforce-description.ts │ │ │ ├── enforce-placeholders.ts │ │ │ ├── enforce-plural-rules.ts │ │ │ ├── no-camel-case.ts │ │ │ ├── no-emoji.ts │ │ │ ├── no-multiple-plurals.ts │ │ │ ├── no-multiple-whitespaces.ts │ │ │ ├── no-offset.ts │ │ │ └── supported-datetime-skeleton.ts │ │ └── util.ts │ ├── tests │ │ ├── blacklist-elements.test.ts │ │ ├── enforce-default-message.test.ts │ │ ├── enforce-description.test.ts │ │ ├── enforce-placeholders.test.ts │ │ ├── enforce-plural-rules.test.ts │ │ ├── fixtures.ts │ │ ├── no-camel-case.test.ts │ │ ├── no-multiple-plurals.test.ts │ │ ├── no-multiple-whitespaces.test.ts │ │ ├── no-offset.test.ts │ │ ├── supported-datetime-skeleton.test.ts │ │ └── util.ts │ └── tsconfig.json ├── formatjs-extract-cldr-data │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── scripts │ │ └── verify-numbers.ts │ ├── src │ │ ├── extract-currencies.ts │ │ ├── extract-displaynames.ts │ │ ├── extract-list.ts │ │ ├── extract-numbers.ts │ │ ├── extract-relative.ts │ │ ├── extract-units.ts │ │ ├── index.ts │ │ ├── locales.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── tests │ │ ├── __snapshots__ │ │ │ ├── extract-currencies.test.ts.snap │ │ │ ├── extract-displaynames.test.ts.snap │ │ │ ├── extract-numbers.test.ts.snap │ │ │ └── extract-units.test.ts.snap │ │ ├── extract-currencies.test.ts │ │ ├── extract-displaynames.test.ts │ │ ├── extract-numbers.test.ts │ │ └── extract-units.test.ts │ └── tsconfig.json ├── intl-displaynames │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── jest.config.js │ ├── package.json │ ├── polyfill.js │ ├── rollup.config.js │ ├── scripts │ │ └── cldr.ts │ ├── src │ │ ├── index.ts │ │ └── polyfill.ts │ ├── tests │ │ ├── index.test.ts │ │ └── runner.ts │ ├── tsconfig.es6.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-format-cache │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── index.ts │ │ └── tsconfig.cjs.json │ ├── tests │ │ ├── benchmark.ts │ │ └── index.ts │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-listformat │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── jest.config.js │ ├── package.json │ ├── polyfill-locales.js │ ├── polyfill.js │ ├── rollup.config.js │ ├── scripts │ │ └── cldr.ts │ ├── src │ │ ├── core.ts │ │ ├── index.ts │ │ ├── polyfill-locales.ts │ │ └── polyfill.ts │ ├── tests │ │ ├── index.test.ts │ │ ├── runner.ts │ │ └── supported-locales-of.test.ts │ ├── tsconfig.es6.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-locales-supported │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ ├── tests │ │ └── index.ts │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-messageformat-parser │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── build.js │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── index.ts │ │ ├── normalize.ts │ │ ├── parser.pegjs │ │ ├── printer.ts │ │ ├── skeleton.ts │ │ └── types.ts │ ├── test │ │ ├── __snapshots__ │ │ │ ├── arg_style.test.ts.snap │ │ │ ├── date_skeleton.test.ts.snap │ │ │ ├── index.test.ts.snap │ │ │ ├── nested.test.ts.snap │ │ │ ├── none_arg.test.ts.snap │ │ │ ├── number_skeleton.test.ts.snap │ │ │ ├── plural_arg.test.ts.snap │ │ │ ├── select_arg.test.ts.snap │ │ │ ├── simple_arg.test.ts.snap │ │ │ ├── string_literal.test.ts.snap │ │ │ └── tag.test.ts.snap │ │ ├── arg_style.test.ts │ │ ├── benchmark.js │ │ ├── date_skeleton.test.ts │ │ ├── error.test.ts │ │ ├── index.test.ts │ │ ├── nested.test.ts │ │ ├── none_arg.test.ts │ │ ├── number_skeleton.test.ts │ │ ├── plural_arg.test.ts │ │ ├── select_arg.test.ts │ │ ├── simple_arg.test.ts │ │ ├── string_literal.test.ts │ │ ├── tag.test.ts │ │ └── unicode_whitespace.test.ts │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-messageformat │ ├── .gitignore │ ├── .npmignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── core.ts │ │ ├── error.ts │ │ ├── formatters.ts │ │ └── index.ts │ ├── tests │ │ ├── benchmark.ts │ │ ├── index.ts │ │ └── setup.js │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-pluralrules │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── jest.config.js │ ├── package.json │ ├── polyfill.js │ ├── rollup.config.js │ ├── scripts │ │ └── cldr.ts │ ├── src │ │ ├── core.ts │ │ ├── index.ts │ │ └── polyfill.ts │ ├── tests │ │ ├── index.test.ts │ │ ├── runner.ts │ │ └── supported-locales-of.test.ts │ ├── tsconfig.es6.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-relativetimeformat │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── jest.config.js │ ├── package.json │ ├── polyfill-locales.js │ ├── polyfill.js │ ├── rollup.config.js │ ├── scripts │ │ └── cldr.ts │ ├── src │ │ ├── core.ts │ │ ├── index.ts │ │ ├── polyfill-locales.ts │ │ ├── polyfill.ts │ │ └── types.ts │ ├── tests │ │ ├── index.test.ts │ │ ├── runner.ts │ │ └── supported-locales-of.test.ts │ ├── tsconfig.es6.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-unified-numberformat │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── jest.config.js │ ├── package.json │ ├── polyfill.js │ ├── rollup.config.js │ ├── scripts │ │ └── cldr.ts │ ├── src │ │ ├── core.ts │ │ ├── data.ts │ │ ├── index.ts │ │ ├── numbering-systems.json │ │ ├── polyfill.ts │ │ └── utils.ts │ ├── tests │ │ ├── __snapshots__ │ │ │ ├── currency-compact.test.ts.snap │ │ │ ├── currency.test.ts.snap │ │ │ ├── decimal.test.ts.snap │ │ │ ├── percent.test.ts.snap │ │ │ └── unit.test.ts.snap │ │ ├── benchmark.ts │ │ ├── currency-compact.test.ts │ │ ├── currency.test.ts │ │ ├── decimal.test.ts │ │ ├── misc.test.ts │ │ ├── notation-compact-ko-KR.test.ts │ │ ├── notation-compact-zh-TW.test.ts │ │ ├── percent.test.ts │ │ ├── runner.ts │ │ ├── signDisplay-currency-zh-TW.test.ts │ │ ├── signDisplay-zh-TW.test.ts │ │ ├── unit-zh-TW.test.ts │ │ ├── unit.test.ts │ │ └── value-tonumber.test.ts │ ├── tsconfig.es6.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── intl-utils │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── api-extractor.json │ ├── package.json │ ├── scripts │ │ └── cldr.ts │ ├── src │ │ ├── diff.ts │ │ ├── displaynames-types.ts │ │ ├── get-canonical-locales.ts │ │ ├── index.ts │ │ ├── invariant.ts │ │ ├── list-types.ts │ │ ├── number-types.ts │ │ ├── plural-rules-types.ts │ │ ├── polyfill-utils.ts │ │ ├── relative-time-types.ts │ │ ├── resolve-locale.ts │ │ ├── types.ts │ │ ├── unified-numberformat-types.ts │ │ └── units.ts │ ├── tests │ │ ├── diff.ts │ │ ├── polyfill-utils.ts │ │ └── resolve-locale.ts │ ├── tsconfig.es6.json │ ├── tsconfig.esm.json │ └── tsconfig.json ├── macro │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json └── ts-transformer │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── compile.ts │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── index.ts │ ├── transform.ts │ └── types.ts │ ├── tests │ ├── __snapshots__ │ │ └── index.test.ts.snap │ ├── fixtures │ │ ├── FormattedMessage.tsx │ │ ├── additionalComponentNames.tsx │ │ ├── defineMessages.tsx │ │ ├── descriptionsAsObjects.tsx │ │ ├── extractFromFormatMessage.tsx │ │ ├── extractSourceLocation.tsx │ │ ├── formatMessageCall.tsx │ │ ├── inline.tsx │ │ ├── moduleSourceName.tsx │ │ ├── noImport.tsx │ │ ├── overrideIdFn.tsx │ │ ├── removeDefaultMessage.tsx │ │ └── removeDescription.tsx │ └── index.test.ts │ └── tsconfig.json ├── rollup.config.js ├── tests ├── ensure_build_output_structure.test.ts ├── ensure_ts_project_reference_in_sync.test.ts ├── jest.config.js └── tsconfig.json ├── tsconfig.json ├── website ├── .gitignore ├── README.md ├── docs │ ├── basic-internationalization-principles.md │ ├── getting-started.md │ ├── icu-syntax.md │ ├── intl-messageformat-parser.md │ ├── intl-messageformat.md │ ├── libraries.md │ ├── polyfills.md │ ├── polyfills │ │ ├── intl-displaynames.md │ │ ├── intl-listformat.md │ │ ├── intl-numberformat.md │ │ ├── intl-pluralrules.md │ │ └── intl-relativetimeformat.md │ ├── react-intl.md │ ├── react-intl │ │ ├── API.md │ │ ├── Advanced-Usage.md │ │ ├── Components.md │ │ ├── Testing-with-React-Intl.md │ │ ├── Upgrade-Guide-2.x.md │ │ └── Upgrade-Guide-3.x.md │ ├── runtime-requirements.md │ └── tooling │ │ ├── babel-plugin.md │ │ ├── cli.md │ │ ├── linter.md │ │ └── ts-transformer.md ├── docusaurus.config.js ├── lang │ ├── strings_cs-CZ.json │ ├── strings_en-US.json │ ├── strings_es-AR.json │ ├── strings_fr-FR.json │ ├── strings_ja-JP.json │ ├── strings_pt-BR.json │ └── strings_sv-SE.json ├── package-lock.json ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ └── styles.module.css └── static │ ├── .nojekyll │ └── img │ ├── chrome.png │ ├── edge.png │ ├── ember.svg │ ├── favicon.ico │ ├── firefox.png │ ├── ie11.png │ ├── js.svg │ ├── logo-dark.svg │ ├── logo-header.svg │ ├── logo.svg │ ├── node.svg │ ├── react.svg │ ├── safari.png │ ├── splash-head.jpg │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ └── undraw_docusaurus_tree.svg └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "pyrocat101", 10 | "name": "Linjie Ding", 11 | "avatar_url": "https://avatars0.githubusercontent.com/u/541540?v=4", 12 | "profile": "https://github.com/pyrocat101", 13 | "contributions": [ 14 | "infra", 15 | "test", 16 | "code" 17 | ] 18 | }, 19 | { 20 | "login": "longlho", 21 | "name": "Long Ho", 22 | "avatar_url": "https://avatars1.githubusercontent.com/u/198255?v=4", 23 | "profile": "https://medium.com/@longho", 24 | "contributions": [ 25 | "infra", 26 | "test", 27 | "code" 28 | ] 29 | } 30 | ], 31 | "contributorsPerLine": 7, 32 | "projectName": "formatjs", 33 | "projectOwner": "formatjs", 34 | "repoType": "github", 35 | "repoHost": "https://github.com", 36 | "skipCi": true 37 | } 38 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /artifacts 2 | /build 3 | /dist 4 | /node_modules 5 | **/artifacts 6 | **/build 7 | **/node_modules 8 | packages/intl-messageformat-parser/src/parser.ts 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | **Which package?** 10 | Since this is a monorepo. Please specify which package this bug report is for. 11 | 12 | **Describe the bug** 13 | A clear and concise description of what the bug is. 14 | 15 | **To Reproduce** 16 | Steps to reproduce the behavior: 17 | 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Screenshots** 27 | If applicable, add screenshots to help explain your problem. 28 | 29 | **Desktop (please complete the following information):** 30 | 31 | - OS: [e.g. iOS] 32 | - Browser [e.g. chrome, safari] 33 | - Version [e.g. 22] 34 | 35 | **Smartphone (please complete the following information):** 36 | 37 | - Device: [e.g. iPhone6] 38 | - OS: [e.g. iOS8.1] 39 | - Browser [e.g. stock browser, safari] 40 | - Version [e.g. 22] 41 | 42 | **Additional context** 43 | Add any other context about the problem here. 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | --- 8 | 9 | **Which package?** 10 | Since this is a monorepo, please specify which package this feature request is for. 11 | 12 | **Is your feature request related to a problem? Please describe.** 13 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | 18 | **Describe alternatives you've considered** 19 | A clear and concise description of any alternative solutions or features you've considered. 20 | 21 | **Additional context** 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [10.x, 12.x, 14.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v1 16 | with: 17 | submodules: true 18 | fetch-depth: 110 19 | - name: Use Node.js ${{ matrix.node-version }} 20 | uses: actions/setup-node@v1 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - name: yarn install 24 | run: | 25 | yarn install --frozen-lockfile 26 | env: 27 | CI: true 28 | - name: yarn build 29 | run: | 30 | yarn build 31 | env: 32 | CI: true 33 | - name: yarn test 34 | run: | 35 | yarn test 36 | env: 37 | CI: true 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | artifacts 2 | .nyc_output 3 | coverage 4 | dist 5 | lib 6 | node_modules 7 | *.log 8 | *.tgz 9 | functional-tests/ 10 | *.tsbuildinfo 11 | .rpt2_cache 12 | test262 13 | temp 14 | polyfill-locales.js 15 | dist-es6 16 | 17 | .now -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test262"] 2 | path = test262 3 | url = https://github.com/tc39/test262.git 4 | shallow = true 5 | -------------------------------------------------------------------------------- /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "reporter": "lcov", 3 | "sourceMap": false, 4 | "instrument": false, 5 | "extends": "@istanbuljs/nyc-config-typescript" 6 | } 7 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | packages/*/CHANGELOG.md 2 | packages/formatjs-extract-cldr-data/src/dateFields.ts 3 | packages/intl-messageformat-parser/src/parser.ts 4 | packages/intl-relativetimeformat/src/en.ts 5 | packages/intl-relativetimeformat/src/locales.ts 6 | packages/intl-unified-numberformat/src/en.ts 7 | packages/intl-unified-numberformat/src/locales.ts 8 | packages/intl-utils/src/aliases.ts 9 | packages/intl-utils/src/parentLocales.ts 10 | packages/intl-listformat/src/locales.ts 11 | packages/babel-plugin-react-intl/src/options.ts 12 | test262/ 13 | website/.docusaurus 14 | website/build 15 | website/.now -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "bracketSpacing": false, 5 | "endOfLine": "lf", 6 | "arrowParens": "avoid" 7 | } 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 12 5 | before_script: 6 | - npm run build 7 | script: npm run karma:ci 8 | addons: 9 | sauce_connect: true 10 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "name": "jest intl-unified-number-format", 10 | "request": "launch", 11 | "cwd": "${workspaceFolder}/packages/intl-unified-numberformat", 12 | "console": "integratedTerminal", 13 | "internalConsoleOptions": "neverOpen", 14 | "disableOptimisticBPs": true, 15 | "program": "${workspaceFolder}/node_modules/jest/bin/jest", 16 | "args": [ 17 | "--runInBand", 18 | "--coverage", 19 | "false", 20 | "notation-compact-zh" 21 | ] 22 | }, 23 | ] 24 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | ".yarn": true 9 | }, 10 | "files.watcherExclude": { 11 | "**/.git/objects/**": true, 12 | "**/.git/subtree-cache/**": true, 13 | "**/node_modules/*/**": true, 14 | "test262/**": true, 15 | "**/test_artifacts/**": true, 16 | "**/*.map": true, 17 | "**/*.d.ts.map": true 18 | }, 19 | "json.schemas": [ 20 | { 21 | "fileMatch": ["/lerna.json"], 22 | "url": "http://json.schemastore.org/lerna" 23 | } 24 | ], 25 | "typescript.tsdk": "node_modules/typescript/lib", 26 | "npm.packageManager": "yarn", 27 | "prettier.packageManager": "yarn", 28 | "eslint.packageManager": "yarn" 29 | } 30 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "dev:cjs", 7 | "problemMatcher": ["$tsc-watch"], 8 | "label": "yarn: dev:cjs", 9 | "detail": "tsc -b packages/* --watch", 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | const {sync: globSync} = require('glob') 2 | const FILES = globSync('./packages/*/tests/browser.js') 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | frameworks: ['mocha', 'chai'], 7 | files: FILES, 8 | reporters: ['progress'], 9 | port: 9876, // karma web server port 10 | colors: true, 11 | logLevel: config.LOG_INFO, 12 | browsers: ['ChromeHeadless'], 13 | autoWatch: false, 14 | singleRun: true, 15 | concurrency: Infinity 16 | }) 17 | } -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "registry": "https://registry.npmjs.org/", 3 | "version": "independent", 4 | "command": { 5 | "version": { 6 | "conventionalCommits": true, 7 | "createRelease": "github" 8 | }, 9 | "run": { 10 | "stream": true 11 | } 12 | }, 13 | "npmClient": "yarn", 14 | "useWorkspaces": true 15 | } 16 | -------------------------------------------------------------------------------- /mocha.opts: -------------------------------------------------------------------------------- 1 | -r ts-node/register 2 | -r source-map-support/register 3 | -r chai/register-expect -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | lib 4 | test/fixtures/*/actual.json 5 | .nyc_output -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | scripts/ 3 | test/ 4 | tests/ 5 | *.log 6 | .rpt2_cache 7 | coverage 8 | *.config.js 9 | tsconfig.* 10 | .nyc_output -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oath Inc. 2 | 3 | Licensed under the terms of the New BSD license. See below for terms. 4 | 5 | Redistribution and use of this software in source and binary forms, 6 | with or without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | - Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the 15 | following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | - Neither the name of Oath Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Oath Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-react-intl 2 | 3 | We've migrated the README to [here](../../website/docs/tooling/babel-plugin.md). 4 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/babel.config.js: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: [ 4 | [ 5 | '@babel/preset-env', 6 | { 7 | targets: { 8 | node: '8' 9 | } 10 | } 11 | ], 12 | '@babel/preset-react' 13 | ] 14 | }; 15 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-react-intl", 3 | "version": "7.5.3", 4 | "description": "Extracts string messages for translation from modules that use React Intl.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/formatjs/formatjs.git" 8 | }, 9 | "license": "BSD-3-Clause", 10 | "main": "dist/index.js", 11 | "types": "dist/index.d.ts", 12 | "files": [ 13 | "dist", 14 | "src" 15 | ], 16 | "author": "Eric Ferraiuolo ", 17 | "dependencies": { 18 | "@babel/core": "^7.9.0", 19 | "@babel/helper-plugin-utils": "^7.8.3", 20 | "@babel/types": "^7.9.5", 21 | "@types/babel__core": "^7.1.7", 22 | "@types/schema-utils": "^2.4.0", 23 | "fs-extra": "^9.0.0", 24 | "intl-messageformat-parser": "^5.0.1", 25 | "schema-utils": "^2.6.6" 26 | }, 27 | "scripts": { 28 | "clean": "rimraf lib dist test/fixtures/**/actual.json *.tsbuildinfo", 29 | "test": "cross-env TS_NODE_PROJECT=./tsconfig.json cross-env NODE_ENV=test jest", 30 | "cover": "npm t -- --coverage", 31 | "build": "json2ts -i src/options.schema.json -o src/options.ts && tsc" 32 | }, 33 | "keywords": [ 34 | "babel-plugin", 35 | "react-intl" 36 | ], 37 | "bugs": { 38 | "url": "https://github.com/formatjs/formatjs/issues" 39 | }, 40 | "homepage": "https://github.com/formatjs/formatjs#readme", 41 | "gitHead": "8b0baec8eda5002715cf893274fe59782fc2d371", 42 | "devDependencies": { 43 | "json-schema-to-typescript": "^8.2.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/src/options.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "moduleSourceName": {"type": "string"}, 5 | "extractSourceLocation": {"type": "boolean"}, 6 | "messagesDir": {"type": "string"}, 7 | "overrideIdFn": { 8 | "instanceof": "Function", 9 | "tsType": "(id: string, defaultMessage: string, description: string, filePath: string) => string" 10 | }, 11 | "removeDefaultMessage": {"type": "boolean"}, 12 | "extractFromFormatMessageCall": {"type": "boolean"}, 13 | "additionalComponentNames": {"type": "array", "items": {"type": "string"}}, 14 | "outputEmptyJson": {"type": "boolean"}, 15 | "pragma": {"type": "string"} 16 | }, 17 | "additionalProperties": false 18 | } 19 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/src/options.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /** 3 | * This file was automatically generated by json-schema-to-typescript. 4 | * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, 5 | * and run json-schema-to-typescript to regenerate this file. 6 | */ 7 | 8 | export interface OptionsSchema { 9 | moduleSourceName?: string; 10 | extractSourceLocation?: boolean; 11 | messagesDir?: string; 12 | overrideIdFn?: (id: string, defaultMessage: string, description: string, filePath: string) => string; 13 | removeDefaultMessage?: boolean; 14 | extractFromFormatMessageCall?: boolean; 15 | additionalComponentNames?: string[]; 16 | outputEmptyJson?: boolean; 17 | pragma?: string; 18 | } 19 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/FormattedMessage/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return ( 7 | 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/additionalComponentNames/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | function CustomMessage() {} 4 | 5 | export default class Foo extends Component { 6 | render() { 7 | return ( 8 | 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/defineMessage/actual.js: -------------------------------------------------------------------------------- 1 | // @react-intl project:amazing 2 | import React, {Component} from 'react'; 3 | import {defineMessage, FormattedMessage} from 'react-intl'; 4 | 5 | const msgs = { 6 | header: defineMessage({ 7 | id: 'foo.bar.baz', 8 | defaultMessage: 'Hello World!', 9 | description: 'The default message', 10 | }), 11 | content: defineMessage({ 12 | id: 'foo.bar.biff', 13 | defaultMessage: 'Hello Nurse!', 14 | description: 'Another message', 15 | }), 16 | kittens: defineMessage({ 17 | id: 'app.home.kittens', 18 | description: 'Counts kittens', 19 | defaultMessage: '{count, plural, =0 {😭} one {# kitten} other {# kittens}}', 20 | }), 21 | trailingWhitespace: defineMessage({ 22 | id: 'trailing.ws', 23 | description: 'Whitespace', 24 | defaultMessage: ' Some whitespace ', 25 | }), 26 | escaped: defineMessage({ 27 | id: 'escaped.apostrophe', 28 | description: 'Escaped apostrophe', 29 | defaultMessage: "A quoted value ''{value}'", 30 | }), 31 | }; 32 | 33 | export default class Foo extends Component { 34 | render() { 35 | return ( 36 |
37 |

38 | 39 |

40 |

41 | 42 |

43 |

44 | 45 |

46 |
47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/defineMessages/actual.js: -------------------------------------------------------------------------------- 1 | // @react-intl project:amazing 2 | import React, {Component} from 'react'; 3 | import {defineMessages, FormattedMessage} from 'react-intl'; 4 | 5 | const msgs = defineMessages({ 6 | header: { 7 | id: 'foo.bar.baz', 8 | defaultMessage: 'Hello World!', 9 | description: 'The default message', 10 | }, 11 | content: { 12 | id: 'foo.bar.biff', 13 | defaultMessage: 'Hello Nurse!', 14 | description: 'Another message', 15 | }, 16 | kittens: { 17 | id: 'app.home.kittens', 18 | description: 'Counts kittens', 19 | defaultMessage: '{count, plural, =0 {😭} one {# kitten} other {# kittens}}', 20 | }, 21 | trailingWhitespace: { 22 | id: 'trailing.ws', 23 | description: 'Whitespace', 24 | defaultMessage: ' Some whitespace ', 25 | }, 26 | escaped: { 27 | id: 'escaped.apostrophe', 28 | description: 'Escaped apostrophe', 29 | defaultMessage: "A quoted value ''{value}'", 30 | }, 31 | }); 32 | 33 | export default class Foo extends Component { 34 | render() { 35 | return ( 36 |
37 |

38 | 39 |

40 |

41 | 42 |

43 |

44 | 45 |

46 |
47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/descriptionsAsObjects/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | // @react-intl project:amazing2 5 | export default class Foo extends Component { 6 | render() { 7 | return ( 8 | 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/empty/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {_} from '@formatjs/macro'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return
; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/enforceDefaultMessage/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage, defineMessages} from 'react-intl'; 3 | 4 | defineMessages({ 5 | test: { 6 | id: 'TRANSLATION_KEY', 7 | }, 8 | }); 9 | 10 | const testMessage = {id: 'TRANSLATION_KEY2'}; 11 | 12 | export default class Foo extends Component { 13 | render() { 14 | return ( 15 | <> 16 | 17 | 18 | 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/enforceDescriptions/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return ; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/extractFromFormatMessageCall/actual.js: -------------------------------------------------------------------------------- 1 | import {FormattedMessage, injectIntl} from 'react-intl'; 2 | import React, {Component} from 'react'; 3 | 4 | const objectPointer = { 5 | id: 'foo.bar.invalid', 6 | defaultMessage: 'This cannot be extracted', 7 | description: 'the plugin only supports inline objects', 8 | }; 9 | 10 | class Foo extends Component { 11 | render() { 12 | const {intl} = this.props; 13 | const { 14 | intl: {formatMessage}, 15 | } = this.props; 16 | const msgs = { 17 | baz: this.props.intl.formatMessage({ 18 | id: 'foo.bar.baz', 19 | defaultMessage: 'Hello World!', 20 | description: 'The default message', 21 | }), 22 | biff: intl.formatMessage({ 23 | id: 'foo.bar.biff', 24 | defaultMessage: 'Hello Nurse!', 25 | description: 'Another message', 26 | }), 27 | qux: formatMessage({ 28 | id: 'foo.bar.qux', 29 | defaultMessage: 'Hello Stranger!', 30 | description: 'A different message', 31 | }), 32 | invalid: this.props.intl.formatMessage(objectPointer), 33 | }; 34 | 35 | return ( 36 |
37 |

{msgs.header}

38 |

{msgs.content}

39 | 40 | 41 | 42 |
43 | ); 44 | } 45 | } 46 | 47 | export default injectIntl(Foo); 48 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/extractFromFormatMessageCallStateless/actual.js: -------------------------------------------------------------------------------- 1 | import {FormattedMessage, injectIntl} from 'react-intl'; 2 | 3 | import React from 'react'; 4 | 5 | const Foo = ({intl: {formatMessage}}) => { 6 | const msgs = { 7 | qux: formatMessage({ 8 | id: 'foo.bar.quux', 9 | defaultMessage: 'Hello Stateless!', 10 | description: 'A stateless message', 11 | }), 12 | }; 13 | 14 | return ( 15 |
16 |

{msgs.header}

17 |

{msgs.content}

18 | 19 | 20 | 21 |
22 | ); 23 | }; 24 | 25 | export default injectIntl(Foo); 26 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/extractSourceLocation/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return ; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/formatMessageCall/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {injectIntl, FormattedMessage} from 'react-intl'; 3 | 4 | const objectPointer = { 5 | id: 'foo.bar.invalid', 6 | defaultMessage: 'This cannot be extracted', 7 | description: 'the plugin only supports inline objects', 8 | }; 9 | 10 | class Foo extends Component { 11 | render() { 12 | const msgs = { 13 | baz: this.props.intl.formatMessage({ 14 | id: 'foo.bar.baz', 15 | defaultMessage: 'Hello World!', 16 | description: 'The default message', 17 | }), 18 | biff: this.props.intl.formatMessage({ 19 | id: 'foo.bar.biff', 20 | defaultMessage: 'Hello Nurse!', 21 | description: 'Another message', 22 | }), 23 | invalid: this.props.intl.formatMessage(objectPointer), 24 | }; 25 | 26 | return ( 27 |
28 |

{msgs.header}

29 |

{msgs.content}

30 | 31 | 32 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | export default injectIntl(Foo); 39 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/icuSyntax/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | // This is bad syntax (object property in message) 7 | return ( 8 | 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/inline/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | import {_} from '@formatjs/macro'; 4 | 5 | export default class Foo extends Component { 6 | render() { 7 | return ( 8 |
9 | 14 | {_({ 15 | id: 'header', 16 | defaultMessage: 'Hello World!', 17 | description: 'The default message', 18 | })} 19 | {_({ 20 | id: 'header2', 21 | defaultMessage: 'Hello World!', 22 | description: 'The default message', 23 | })} 24 |
25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/moduleSourceName/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-i18n'; 3 | import {defineMessages} from 'react-intl'; 4 | 5 | // These should be ignored because the `moduleSourceName` is configured to be: 6 | // `react-i18n`. 7 | const msgs = defineMessages({ 8 | header: { 9 | id: 'header', 10 | defaultMessage: 'Hello World!', 11 | description: 'The default message', 12 | }, 13 | content: { 14 | id: 'content', 15 | defaultMessage: 'Hello Nurse!', 16 | description: 'Another message', 17 | }, 18 | }); 19 | 20 | export default class Foo extends Component { 21 | render() { 22 | return ( 23 |
24 | 29 | {msgs} 30 |
31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/outputEmptyJson/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {_} from '@formatjs/macro'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return
; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/overrideIdFn/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const msgs = defineMessages({ 5 | header: { 6 | id: 'foo.bar.baz', 7 | defaultMessage: 'Hello World!', 8 | description: 'The default message', 9 | }, 10 | content: { 11 | id: 'foo.bar.biff', 12 | defaultMessage: 'Hello Nurse!', 13 | description: { 14 | text: 'Something for the translator.', 15 | metadata: 'Additional metadata content.', 16 | }, 17 | }, 18 | }); 19 | 20 | export default class Foo extends Component { 21 | render() { 22 | return ( 23 |
24 |

25 | 26 |

27 |

28 | 29 |

30 | 38 | 45 |
46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/removeDefaultMessage/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const messages = defineMessages({ 5 | foo: { 6 | id: 'greeting-user', 7 | description: 'Greeting the user', 8 | defaultMessage: 'Hello, {name}', 9 | }, 10 | }); 11 | 12 | export default class Foo extends Component { 13 | render() { 14 | return ( 15 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/test/fixtures/removeDescriptions/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const messages = defineMessages({ 5 | foo: { 6 | id: 'greeting-user', 7 | description: 'Greeting the user', 8 | defaultMessage: 'Hello, {name}', 9 | }, 10 | }); 11 | 12 | export default class Foo extends Component { 13 | render() { 14 | return ( 15 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/babel-plugin-react-intl/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "baseUrl": ".", 7 | "types": [ 8 | "babel__core", 9 | "babel__generator", 10 | "babel__template", 11 | "babel__traverse", 12 | "benchmark", 13 | "chai", 14 | "estree", 15 | "fs-extra", 16 | "istanbul-lib-coverage", 17 | "istanbul-lib-report", 18 | "istanbul-reports", 19 | // Don't include mocha here 20 | "jest", 21 | "jest-diff", 22 | "node", 23 | "resolve", 24 | "stack-utils", 25 | "yargs" 26 | ], 27 | "sourceMap": true, 28 | "esModuleInterop": true 29 | }, 30 | "include": ["src", "src/**/*.json"], 31 | "references": [{"path": "../intl-messageformat-parser"}] 32 | } 33 | -------------------------------------------------------------------------------- /packages/cli/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/cli/README.md: -------------------------------------------------------------------------------- 1 | # @formatjs/cli 2 | 3 | We've migrated the README to [here](../../website/docs/tooling/cli.md). 4 | -------------------------------------------------------------------------------- /packages/cli/bin/formatjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | require('../lib/cli').default(process.argv); 6 | -------------------------------------------------------------------------------- /packages/cli/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | // TODO: figure out editor tsconfig 7 | tsConfig: 'tsconfig.jest.json' 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/cli", 3 | "version": "1.6.8", 4 | "description": "A CLI for formatjs.", 5 | "keywords": [ 6 | "intl", 7 | "i18n", 8 | "internationalization", 9 | "locale", 10 | "localization", 11 | "globalization", 12 | "react", 13 | "react-intl", 14 | "reactjs", 15 | "format", 16 | "formatjs", 17 | "formatting", 18 | "translate", 19 | "translation", 20 | "cli" 21 | ], 22 | "author": "Linjie Ding ", 23 | "homepage": "https://github.com/formatjs/formatjs", 24 | "license": "MIT", 25 | "main": "lib/index.js", 26 | "bin": { 27 | "formatjs": "bin/formatjs" 28 | }, 29 | "files": [ 30 | "bin", 31 | "lib", 32 | "src" 33 | ], 34 | "repository": { 35 | "type": "git", 36 | "url": "git+ssh://git@github.com/formatjs/formatjs.git" 37 | }, 38 | "scripts": { 39 | "clean": "rimraf lib dist *.tsbuildinfo", 40 | "build": "tsc", 41 | "test": "cross-env TS_NODE_PROJECT=./tsconfig.jest.json cross-env NODE_ENV=test jest" 42 | }, 43 | "dependencies": { 44 | "@babel/plugin-proposal-class-properties": "^7.8.3", 45 | "@babel/plugin-proposal-optional-chaining": "7", 46 | "@babel/preset-env": "^7.9.5", 47 | "@babel/preset-typescript": "^7.9.0", 48 | "@types/babel__core": "^7.1.7", 49 | "@types/loader-utils": "^1.1.3", 50 | "@types/lodash": "^4.14.150", 51 | "babel-plugin-const-enum": "^1.0.1", 52 | "babel-plugin-react-intl": "^7.5.3", 53 | "commander": "5.0.0", 54 | "fs-extra": "^9.0.0", 55 | "glob": "^7.1.6", 56 | "loader-utils": "^2.0.0", 57 | "lodash": "^4.17.15", 58 | "loud-rejection": "^2.2.0" 59 | }, 60 | "bugs": { 61 | "url": "https://github.com/formatjs/formatjs/issues" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/cli/src/console_utils.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | import readline from 'readline'; 3 | import tty from 'tty'; 4 | 5 | const CLEAR_WHOLE_LINE = 0; 6 | 7 | // From: 8 | // https://github.com/yarnpkg/yarn/blob/53d8004229f543f342833310d5af63a4b6e59c8a/src/reporters/console/util.js 9 | export function clearLine(terminal: NodeJS.WriteStream) { 10 | if (!chalk.supportsColor) { 11 | if (terminal instanceof tty.WriteStream) { 12 | // terminal 13 | if (terminal.columns > 0) { 14 | terminal.write(`\r${' '.repeat(terminal.columns - 1)}`); 15 | } 16 | terminal.write(`\r`); 17 | } 18 | // ignore piping to file 19 | } else { 20 | readline.clearLine(terminal, CLEAR_WHOLE_LINE); 21 | readline.cursorTo(terminal, 0); 22 | } 23 | } 24 | 25 | export function warn(message: string): void { 26 | clearLine(process.stderr); 27 | process.stderr.write(`${chalk.yellow('warning')} ${message}\n`); 28 | } 29 | 30 | export function error(message: string): void { 31 | clearLine(process.stderr); 32 | process.stderr.write(`${chalk.red('error')} ${message}\n`); 33 | } 34 | 35 | export async function getStdinAsString(): Promise { 36 | let result = ''; 37 | return new Promise(resolve => { 38 | process.stdin.setEncoding('utf-8'); 39 | process.stdin.on('readable', () => { 40 | let chunk; 41 | while ((chunk = process.stdin.read())) { 42 | result += chunk; 43 | } 44 | }); 45 | process.stdin.on('end', () => { 46 | resolve(result); 47 | }); 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /packages/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | default as extractAndWrite, 3 | extract, 4 | ExtractCLIOptions, 5 | } from './extract'; 6 | -------------------------------------------------------------------------------- /packages/cli/tests/extract/integration_tests/.gitignore: -------------------------------------------------------------------------------- 1 | test_artifacts 2 | -------------------------------------------------------------------------------- /packages/cli/tests/extract/integration_tests/defineMessages/actual.ignore.js: -------------------------------------------------------------------------------- 1 | // @react-intl project:foo 2 | import React, {Component} from 'react'; 3 | import {defineMessages, FormattedMessage} from 'react-intl'; 4 | 5 | const msgs = defineMessages({ 6 | test: { 7 | id: 'ignore', 8 | defaultMessage: 'ignore', 9 | }, 10 | }); 11 | 12 | export default class Foo extends Component { 13 | render() { 14 | return ( 15 |
16 |

17 | 18 |

19 |
20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/cli/tests/extract/integration_tests/defineMessages/actual.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const msgs = defineMessages({ 5 | header: { 6 | id: 'foo.bar.baz', 7 | defaultMessage: 'Hello World!', 8 | description: 'The default message', 9 | }, 10 | content: { 11 | id: 'foo.bar.biff', 12 | defaultMessage: 'Hello Nurse!', 13 | description: 'Another message', 14 | }, 15 | kittens: { 16 | id: 'app.home.kittens', 17 | description: 'Counts kittens', 18 | defaultMessage: '{count, plural, =0 {😭} one {# kitten} other {# kittens}}', 19 | }, 20 | trailingWhitespace: { 21 | id: 'trailing.ws', 22 | description: 'Whitespace', 23 | defaultMessage: ' Some whitespace ', 24 | }, 25 | escaped: { 26 | id: 'escaped.apostrophe', 27 | description: 'Escaped apostrophe', 28 | defaultMessage: "A quoted value ''{value}'", 29 | }, 30 | noId: { 31 | description: 'no ID', 32 | defaultMessage: "No ID", 33 | }, 34 | duplicateAsNoId: { 35 | description: 'no ID', 36 | defaultMessage: "No ID", 37 | } 38 | }); 39 | 40 | export default class Foo extends Component { 41 | render() { 42 | const msg = msgs?.header 43 | return ( 44 |
45 |

46 | 47 |

48 |

49 | 50 |

51 |

52 | 53 |

54 |
55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/cli/tests/extract/integration_tests/defineMessages/actual.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "foo.bar.baz", 4 | "description": "The default message", 5 | "defaultMessage": "Hello World!" 6 | }, 7 | { 8 | "id": "foo.bar.biff", 9 | "description": "Another message", 10 | "defaultMessage": "Hello Nurse!" 11 | }, 12 | { 13 | "id": "app.home.kittens", 14 | "description": "Counts kittens", 15 | "defaultMessage": "{count, plural, =0 {😭} one {# kitten} other {# kittens}}" 16 | }, 17 | { 18 | "id": "trailing.ws", 19 | "description": "Whitespace", 20 | "defaultMessage": " Some whitespace " 21 | }, 22 | { 23 | "id": "escaped.apostrophe", 24 | "description": "Escaped apostrophe", 25 | "defaultMessage": "A quoted value ''{value}'" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /packages/cli/tests/extract/integration_tests/typescript/actual.ignore.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const msgs = defineMessages({ 5 | test: { 6 | id: 'ignore', 7 | defaultMessage: 'ignore', 8 | }, 9 | }); 10 | 11 | export default class Foo extends Component { 12 | render() { 13 | return ( 14 |
15 |

16 | 17 |

18 |
19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/cli/tests/extract/integration_tests/typescript/actual.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "foo.bar.baz", 4 | "description": "The default message", 5 | "defaultMessage": "Hello World!" 6 | }, 7 | { 8 | "id": "foo.bar.biff", 9 | "description": "Another message", 10 | "defaultMessage": "Hello Nurse!" 11 | }, 12 | { 13 | "id": "app.home.kittens", 14 | "description": "Counts kittens", 15 | "defaultMessage": "{count, plural, =0 {😭} one {# kitten} other {# kittens}}" 16 | }, 17 | { 18 | "id": "trailing.ws", 19 | "description": "Whitespace", 20 | "defaultMessage": " Some whitespace " 21 | }, 22 | { 23 | "id": "escaped.apostrophe", 24 | "description": "Escaped apostrophe", 25 | "defaultMessage": "A quoted value ''{value}'" 26 | } 27 | ] 28 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | }, 6 | "include": ["src/**/*.ts", "tests/**/*.ts"], 7 | "exclude": ["tests/extract/integration_tests/typescript/**/*.tsx"], 8 | } 9 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | // Targeting node >= 8 5 | "target": "es2017", 6 | "outDir": "lib", 7 | "rootDir": "src", 8 | "esModuleInterop": true, 9 | "noUnusedLocals": true, 10 | "sourceMap": true, 11 | "allowSyntheticDefaultImports": true, 12 | "types": [ 13 | "babel__core", 14 | "babel__generator", 15 | "babel__template", 16 | "babel__traverse", 17 | "benchmark", 18 | "chai", 19 | "estree", 20 | "fs-extra", 21 | "istanbul-lib-coverage", 22 | "istanbul-lib-report", 23 | "istanbul-reports", 24 | // Don't include mocha here 25 | "jest", 26 | "node", 27 | "resolve", 28 | "stack-utils", 29 | "yargs" 30 | ] 31 | }, 32 | "include": ["src/**/*.ts"], 33 | "references": [{"path": "../babel-plugin-react-intl"}] 34 | } 35 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/README.md: -------------------------------------------------------------------------------- 1 | # eslint-plugin-formatjs 2 | 3 | We've migrated the README to [here](../../website/docs/tooling/linter.md). 4 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-plugin-formatjs", 3 | "version": "2.2.2", 4 | "description": "ESLint plugin for formatjs", 5 | "main": "dist/index.js", 6 | "files": [ 7 | "dist", 8 | "src" 9 | ], 10 | "scripts": { 11 | "build": "tsc", 12 | "test": "cross-env TS_NODE_PROJECT=./tsconfig.json cross-env NODE_ENV=test jest" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+ssh://git@github.com/formatjs/formatjs.git" 17 | }, 18 | "keywords": [ 19 | "eslint", 20 | "eslintplugin", 21 | "i18n", 22 | "formatjs" 23 | ], 24 | "author": "Long Ho ", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/formatjs/formatjs/issues" 28 | }, 29 | "homepage": "https://github.com/formatjs/formatjs#readme", 30 | "dependencies": { 31 | "@types/emoji-regex": "^8.0.0", 32 | "@typescript-eslint/typescript-estree": "^2.29.0", 33 | "emoji-regex": "^9.0.0", 34 | "intl-messageformat-parser": "^5.0.1" 35 | }, 36 | "peerDependencies": { 37 | "eslint": "^6.8.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/src/index.ts: -------------------------------------------------------------------------------- 1 | import enforceDescription from './rules/enforce-description'; 2 | import enforceDefaultMessage from './rules/enforce-default-message'; 3 | import noCamelCase from './rules/no-camel-case'; 4 | import noEmoji from './rules/no-emoji'; 5 | import noMultiplePlurals from './rules/no-multiple-plurals'; 6 | import noOffset from './rules/no-offset'; 7 | import blacklistElements from './rules/blacklist-elements'; 8 | import enforcePluralRules from './rules/enforce-plural-rules'; 9 | import enforcePlaceholders from './rules/enforce-placeholders'; 10 | import enforceSupportedDateTimeSkeleton from './rules/supported-datetime-skeleton'; 11 | import noMultipleWhitespaces from './rules/no-multiple-whitespaces'; 12 | const plugin = { 13 | rules: { 14 | 'enforce-description': enforceDescription, 15 | 'enforce-default-message': enforceDefaultMessage, 16 | 'no-camel-case': noCamelCase, 17 | 'no-emoji': noEmoji, 18 | 'no-multiple-plurals': noMultiplePlurals, 19 | 'no-offset': noOffset, 20 | 'blacklist-elements': blacklistElements, 21 | 'enforce-plural-rules': enforcePluralRules, 22 | 'enforce-placeholders': enforcePlaceholders, 23 | 'supported-datetime-skeleton': enforceSupportedDateTimeSkeleton, 24 | 'no-multiple-whitespaces': noMultipleWhitespaces, 25 | }, 26 | }; 27 | 28 | export type Plugin = typeof plugin; 29 | 30 | module.exports = plugin; 31 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/blacklist-elements.test.ts: -------------------------------------------------------------------------------- 1 | import blacklistElements from '../src/rules/blacklist-elements'; 2 | import {ruleTester} from './util'; 3 | import {dynamicMessage, noMatch, spreadJsx, emptyFnCall} from './fixtures'; 4 | ruleTester.run('blacklist-elements', blacklistElements, { 5 | valid: [ 6 | { 7 | code: `import {_} from '@formatjs/macro' 8 | _({ 9 | defaultMessage: '{count, plural, one {#} other {# more}}' 10 | })`, 11 | options: [['selectordinal']], 12 | }, 13 | dynamicMessage, 14 | noMatch, 15 | spreadJsx, 16 | emptyFnCall, 17 | ], 18 | invalid: [ 19 | { 20 | code: ` 21 | import {_} from '@formatjs/macro' 22 | _({ 23 | defaultMessage: '{count, selectordinal, offset:1 one {#} other {# more}}' 24 | })`, 25 | options: [['selectordinal']], 26 | errors: [ 27 | { 28 | message: 'selectordinal element is blacklisted', 29 | }, 30 | ], 31 | }, 32 | ], 33 | }); 34 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/fixtures.ts: -------------------------------------------------------------------------------- 1 | export const noMatch = `_()`; 2 | export const emptyFnCall = ` 3 | import {_} from '@formatjs/macro' 4 | _()`; 5 | export const spreadJsx = ` 6 | import {FormattedMessage} from 'react-intl' 7 | function foo (props) { 8 | return ( 9 | 10 | ) 11 | } 12 | `; 13 | export const dynamicMessage = ` 14 | import {_} from '@formatjs/macro' 15 | _({ 16 | id, 17 | defaultMessage, 18 | description 19 | })`; 20 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/no-camel-case.test.ts: -------------------------------------------------------------------------------- 1 | import {ruleTester} from './util'; 2 | import noCamelCase from '../src/rules/no-camel-case'; 3 | import {dynamicMessage, noMatch, spreadJsx, emptyFnCall} from './fixtures'; 4 | 5 | ruleTester.run('no-camel-case', noCamelCase, { 6 | valid: [ 7 | `import {_} from '@formatjs/macro' 8 | _({ 9 | defaultMessage: 'a {placeholder}', 10 | description: 'asd' 11 | })`, 12 | dynamicMessage, 13 | noMatch, 14 | spreadJsx, 15 | emptyFnCall, 16 | ], 17 | invalid: [ 18 | { 19 | code: ` 20 | import {_} from '@formatjs/macro' 21 | _({ 22 | defaultMessage: 'a {placeHolder}' 23 | })`, 24 | errors: [ 25 | { 26 | message: 'Camel case arguments are not allowed', 27 | }, 28 | ], 29 | }, 30 | ], 31 | }); 32 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/no-multiple-plurals.test.ts: -------------------------------------------------------------------------------- 1 | import noMultiplePlurals from '../src/rules/no-multiple-plurals'; 2 | import {ruleTester} from './util'; 3 | import {dynamicMessage, noMatch, spreadJsx, emptyFnCall} from './fixtures'; 4 | ruleTester.run('no-multiple-plurals', noMultiplePlurals, { 5 | valid: [ 6 | `import {_} from '@formatjs/macro' 7 | _({ 8 | defaultMessage: 'a {placeholder}', 9 | description: 'asd' 10 | })`, 11 | dynamicMessage, 12 | noMatch, 13 | spreadJsx, 14 | emptyFnCall, 15 | ], 16 | invalid: [ 17 | { 18 | code: ` 19 | import {_} from '@formatjs/macro' 20 | _({ 21 | defaultMessage: '{p1, plural, one{one}} {p2, plural, one{two}}' 22 | })`, 23 | errors: [ 24 | { 25 | message: 'Cannot specify more than 1 plural rules', 26 | }, 27 | ], 28 | }, 29 | { 30 | code: ` 31 | import {_} from '@formatjs/macro' 32 | _({ 33 | defaultMessage: '{p1, plural, one{{p2, plural, one{two}}}}' 34 | })`, 35 | errors: [ 36 | { 37 | message: 'Cannot specify more than 1 plural rules', 38 | }, 39 | ], 40 | }, 41 | ], 42 | }); 43 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/no-multiple-whitespaces.test.ts: -------------------------------------------------------------------------------- 1 | import noMultipleWhitespaces from '../src/rules/no-multiple-whitespaces'; 2 | import {ruleTester} from './util'; 3 | import {dynamicMessage, noMatch, spreadJsx, emptyFnCall} from './fixtures'; 4 | ruleTester.run('no-multiple-whitespaces', noMultipleWhitespaces, { 5 | valid: [ 6 | `import {_} from '@formatjs/macro' 7 | _({ 8 | defaultMessage: 'a {placeholder}', 9 | description: 'asd' 10 | })`, 11 | dynamicMessage, 12 | noMatch, 13 | spreadJsx, 14 | emptyFnCall, 15 | ], 16 | invalid: [ 17 | { 18 | code: 19 | "import {_} from '@formatjs/macro';_({defaultMessage: 'a \ 20 | {placeHolder}'})", 21 | errors: [ 22 | { 23 | message: 'Multiple consecutive whitespaces are not allowed', 24 | }, 25 | ], 26 | output: 27 | "import {_} from '@formatjs/macro';_({defaultMessage: 'a {placeHolder}'})", 28 | }, 29 | { 30 | code: "", 31 | errors: [ 32 | { 33 | message: 'Multiple consecutive whitespaces are not allowed', 34 | }, 35 | ], 36 | output: "", 37 | }, 38 | { 39 | code: ` 40 | import {_} from '@formatjs/macro' 41 | _({ 42 | defaultMessage: 'a {placeHolder}' 43 | })`, 44 | errors: [ 45 | { 46 | message: 'Multiple consecutive whitespaces are not allowed', 47 | }, 48 | ], 49 | output: ` 50 | import {_} from '@formatjs/macro' 51 | _({ 52 | defaultMessage: 'a {placeHolder}' 53 | })`, 54 | }, 55 | ], 56 | }); 57 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/no-offset.test.ts: -------------------------------------------------------------------------------- 1 | import noOffset from '../src/rules/no-offset'; 2 | import {ruleTester} from './util'; 3 | import {dynamicMessage, noMatch, spreadJsx, emptyFnCall} from './fixtures'; 4 | ruleTester.run('no-offset', noOffset, { 5 | valid: [ 6 | `import {_} from '@formatjs/macro' 7 | _({ 8 | defaultMessage: '{count, plural, one {#} other {# more}}' 9 | })`, 10 | dynamicMessage, 11 | noMatch, 12 | spreadJsx, 13 | emptyFnCall, 14 | ], 15 | invalid: [ 16 | { 17 | code: ` 18 | import {_} from '@formatjs/macro' 19 | _({ 20 | defaultMessage: '{count, plural, offset:1 one {#} other {# more}}' 21 | })`, 22 | errors: [ 23 | { 24 | message: 'offset are not allowed in plural rules', 25 | }, 26 | ], 27 | }, 28 | { 29 | code: ` 30 | import {_} from '@formatjs/macro' 31 | _({ 32 | defaultMessage: '{count, plural, offset:1 one {#} other {# more}' 33 | })`, 34 | errors: [ 35 | { 36 | message: 'Expected "=", "}", or argName but end of input found.', 37 | }, 38 | ], 39 | }, 40 | ], 41 | }); 42 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/supported-datetime-skeleton.test.ts: -------------------------------------------------------------------------------- 1 | import supportedDatetimeSkeleton from '../src/rules/supported-datetime-skeleton'; 2 | import {ruleTester} from './util'; 3 | import {dynamicMessage, noMatch, spreadJsx, emptyFnCall} from './fixtures'; 4 | ruleTester.run('supported-datetime-skeleton', supportedDatetimeSkeleton, { 5 | valid: [ 6 | `import {_} from '@formatjs/macro' 7 | _({ 8 | defaultMessage: '{ts, date, ::yyyyMMdd}' 9 | })`, 10 | dynamicMessage, 11 | noMatch, 12 | spreadJsx, 13 | emptyFnCall, 14 | ], 15 | invalid: [ 16 | { 17 | code: ` 18 | import {_} from '@formatjs/macro' 19 | _({ 20 | defaultMessage: '{ts, date, ::yQQQHm}' 21 | })`, 22 | errors: [ 23 | { 24 | message: '`q/Q` (quarter) patterns are not supported', 25 | }, 26 | ], 27 | }, 28 | { 29 | code: ` 30 | import {_} from '@formatjs/macro' 31 | _({ 32 | defaultMessage: '{ts, date, ::DFg}' 33 | })`, 34 | errors: [ 35 | { 36 | message: '`D/F/g` (day) patterns are not supported, use `d` instead', 37 | }, 38 | ], 39 | }, 40 | ], 41 | }); 42 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tests/util.ts: -------------------------------------------------------------------------------- 1 | import {RuleTester} from 'eslint'; 2 | 3 | export const ruleTester = new RuleTester({ 4 | parser: require.resolve('@typescript-eslint/parser'), 5 | parserOptions: { 6 | ecmaVersion: 6, 7 | sourceType: 'module', 8 | ecmaFeatures: { 9 | modules: true, 10 | jsx: true, 11 | }, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /packages/eslint-plugin-formatjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "noUnusedLocals": true, 8 | "sourceMap": true, 9 | "preserveConstEnums": false, 10 | "types": [ 11 | "eslint", 12 | "babel__core", 13 | "babel__generator", 14 | "babel__template", 15 | "babel__traverse", 16 | "benchmark", 17 | "chai", 18 | "fs-extra", 19 | "istanbul-lib-coverage", 20 | "istanbul-lib-report", 21 | "istanbul-reports", 22 | // Don't include mocha here 23 | "jest", 24 | "node", 25 | "resolve", 26 | "stack-utils", 27 | "yargs" 28 | ] 29 | }, 30 | "include": ["src/**/*.ts"], 31 | "references": [{"path": "../intl-messageformat-parser"}] 32 | } 33 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/.gitignore: -------------------------------------------------------------------------------- 1 | src/dateFields.ts 2 | src/units.ts -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oath Inc. 2 | 3 | Licensed under the terms of the New BSD license. See below for terms. 4 | 5 | Redistribution and use of this software in source and binary forms, 6 | with or without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | - Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the 15 | following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | - Neither the name of Oath Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Oath Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formatjs-extract-cldr-data", 3 | "version": "10.1.5", 4 | "description": "Utility library that extracts the CLDR data that's needed by the FormatJS libraries.", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "files": [ 8 | "dist", 9 | "lib", 10 | "src" 11 | ], 12 | "scripts": { 13 | "build": "tsc", 14 | "clean": "rimraf dist *.tsbuildinfo", 15 | "test": "cross-env TS_NODE_PROJECT=./tsconfig.json cross-env NODE_ENV=test jest --maxWorkers=100%", 16 | "verify": "ts-node scripts/verify-numbers", 17 | "cover": "npm t -- --coverage" 18 | }, 19 | "author": "Eric Ferraiuolo ", 20 | "license": "BSD-3-Clause", 21 | "dependencies": { 22 | "@formatjs/intl-utils": "^2.2.3", 23 | "@types/glob": "^7.1.1", 24 | "@types/lodash": "^4.14.150", 25 | "cldr-core": "^36.0.0", 26 | "cldr-dates-full": "^36.0.0", 27 | "cldr-localenames-full": "^36.0.0", 28 | "cldr-misc-full": "^36.0.0", 29 | "cldr-numbers-full": "^36.0.0", 30 | "cldr-units-full": "^36.0.0", 31 | "glob": "^7.1.6", 32 | "lodash": "^4.17.15" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "https://github.com/formatjs/formatjs.git" 37 | }, 38 | "keywords": [ 39 | "i18n", 40 | "cldr", 41 | "formatjs" 42 | ], 43 | "bugs": { 44 | "url": "https://github.com/formatjs/formatjs/issues" 45 | }, 46 | "homepage": "https://github.com/formatjs/formatjs", 47 | "gitHead": "a7842673d8ad205171ad7c8cb8bb2f318b427c0c" 48 | } 49 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/scripts/verify-numbers.ts: -------------------------------------------------------------------------------- 1 | import {sync as globSync} from 'glob'; 2 | import {resolve, dirname} from 'path'; 3 | import * as Numbers from 'cldr-numbers-full/main/en/numbers.json'; 4 | 5 | const numberDataFiles = globSync('*/numbers.json', { 6 | cwd: resolve( 7 | dirname(require.resolve('cldr-numbers-full/package.json')), 8 | './main' 9 | ), 10 | }).map(p => `cldr-numbers-full/main/${p}`); 11 | 12 | const numbersData: Array = numberDataFiles.map(p => require(p)); 13 | 14 | numbersData.forEach(d => { 15 | const locale = Object.keys(d.main)[0] as 'en'; 16 | const data = d.main[locale].numbers; 17 | if (data['scientificFormats-numberSystem-latn'].standard !== '#E0') { 18 | console.log( 19 | `${locale} has uncommon (#E0) scientific format: ${data['scientificFormats-numberSystem-latn'].standard}` 20 | ); 21 | } 22 | // if (data['percentFormats-numberSystem-latn'].standard !== '#,##0%') { 23 | // console.log( 24 | // `${locale} has uncommon (#,##0%) percent format: ${data['percentFormats-numberSystem-latn'].standard}` 25 | // ); 26 | // } 27 | if ( 28 | data['currencyFormats-numberSystem-latn'].currencySpacing.afterCurrency 29 | .currencyMatch !== '[:^S:]' 30 | ) { 31 | console.log( 32 | `${locale} has uncommon ([:^S:]) currencySpacing: ${data['currencyFormats-numberSystem-latn'].currencySpacing.afterCurrency.currencyMatch}` 33 | ); 34 | } 35 | if ( 36 | data['currencyFormats-numberSystem-latn'].currencySpacing.afterCurrency 37 | .insertBetween !== 38 | data['currencyFormats-numberSystem-latn'].currencySpacing.beforeCurrency 39 | .insertBetween 40 | ) { 41 | console.log( 42 | `${locale} has different insertBetween between before and after` 43 | ); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/src/locales.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, Yahoo Inc. 3 | * Copyrights licensed under the New BSD License. 4 | * See the accompanying LICENSE file for terms. 5 | */ 6 | // These are the exceptions to the default algorithm for determining a locale's 7 | // parent locale. 8 | import * as AVAILABLE_LOCALES from 'cldr-core/availableLocales.json'; 9 | 10 | export function getAllLocales() { 11 | return AVAILABLE_LOCALES.availableLocales.full.sort(); 12 | } 13 | 14 | export function getAllLanguages() { 15 | return new Set( 16 | AVAILABLE_LOCALES.availableLocales.full.map(l => l.split('-')[0]) 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/src/types.ts: -------------------------------------------------------------------------------- 1 | export type Locale = string; 2 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/tests/extract-currencies.test.ts: -------------------------------------------------------------------------------- 1 | import extractCurrencies from '../src/extract-currencies'; 2 | 3 | describe('extract-currencies', function () { 4 | it('should be able to extract en', function () { 5 | expect(extractCurrencies(['en'])).toMatchSnapshot(); 6 | }); 7 | it('should be able to extract uk', function () { 8 | expect(extractCurrencies(['uk'])).toMatchSnapshot(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/tests/extract-displaynames.test.ts: -------------------------------------------------------------------------------- 1 | import extractDisplayNames from '../src/extract-displaynames'; 2 | 3 | describe('extract-units', function () { 4 | it('should be able to extract en', function () { 5 | expect(extractDisplayNames(['en'])).toMatchSnapshot(); 6 | }); 7 | it('should be able to extract vi', function () { 8 | expect(extractDisplayNames(['vi'])).toMatchSnapshot(); 9 | }); 10 | it('should be able to extract ja', function () { 11 | expect(extractDisplayNames(['ja'])).toMatchSnapshot(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/tests/extract-numbers.test.ts: -------------------------------------------------------------------------------- 1 | import extractNumbers from '../src/extract-numbers'; 2 | 3 | describe('extract-numbers', function () { 4 | it('should be able to extract en', function () { 5 | expect(extractNumbers(['en'])).toMatchSnapshot(); 6 | }); 7 | it('should be able to extract vi', function () { 8 | expect(extractNumbers(['vi'])).toMatchSnapshot(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/tests/extract-units.test.ts: -------------------------------------------------------------------------------- 1 | import extractUnits from '../src/extract-units'; 2 | 3 | describe('extract-units', function () { 4 | it('should be able to extract en', function () { 5 | expect(extractUnits(['en'])).toMatchSnapshot(); 6 | }); 7 | it('should be able to extract vi', function () { 8 | expect(extractUnits(['vi'])).toMatchSnapshot(); 9 | }); 10 | it('should be able to extract ja', function () { 11 | expect(extractUnits(['ja'])).toMatchSnapshot(); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/formatjs-extract-cldr-data/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "types": [ 7 | "babel__core", 8 | "babel__generator", 9 | "babel__template", 10 | "babel__traverse", 11 | "benchmark", 12 | "chai", 13 | "estree", 14 | "fs-extra", 15 | "istanbul-lib-coverage", 16 | "istanbul-lib-report", 17 | "istanbul-reports", 18 | // Don't include mocha here 19 | "jest", 20 | "jest-diff", 21 | "node", 22 | "resolve", 23 | "stack-utils", 24 | "yargs" 25 | ] 26 | }, 27 | "include": ["src"], 28 | "references": [{"path": "../intl-utils"}] 29 | } 30 | -------------------------------------------------------------------------------- /packages/intl-displaynames/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/packages/intl-displaynames/.gitignore -------------------------------------------------------------------------------- /packages/intl-displaynames/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/intl-displaynames/README.md: -------------------------------------------------------------------------------- 1 | # `intl-displaynames` 2 | 3 | We've migrated the README to [here](../../website/docs/polyfills/intl-displaynames.md). 4 | -------------------------------------------------------------------------------- /packages/intl-displaynames/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } 4 | -------------------------------------------------------------------------------- /packages/intl-displaynames/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/intl-displaynames/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/intl-displaynames", 3 | "version": "1.2.7", 4 | "description": "Polyfill for: https://tc39.es/proposal-intl-displaynames", 5 | "keywords": [ 6 | "i18n", 7 | "polyfill", 8 | "intl-polyfill", 9 | "localization", 10 | "formatjs", 11 | "Intl.DisplayNames", 12 | "Intl" 13 | ], 14 | "author": "Linjie Ding ", 15 | "homepage": "https://github.com/formatjs/formatjs", 16 | "license": "MIT", 17 | "main": "dist/index.js", 18 | "module": "lib/index.js", 19 | "module:es6": "dist-es6/index.js", 20 | "types": "lib/index.d.js", 21 | "files": [ 22 | "dist", 23 | "lib", 24 | "polyfill.js", 25 | "polyfill-locales.js", 26 | "src" 27 | ], 28 | "repository": { 29 | "type": "git", 30 | "url": "git+https://github.com/formatjs/formatjs.git" 31 | }, 32 | "dependencies": { 33 | "@formatjs/intl-utils": "^2.2.3" 34 | }, 35 | "devDependencies": { 36 | "formatjs-extract-cldr-data": "^10.1.5" 37 | }, 38 | "scripts": { 39 | "cldr": "ts-node scripts/cldr", 40 | "build": "yarn run cldr && yarn run compile && yarn run rollup", 41 | "clean": "rimraf dist dist-es6 lib *.tsbuildinfo", 42 | "jest": "cross-env NODE_ICU_DATA=../../node_modules/full-icu cross-env NODE_ENV=test jest", 43 | "test262": "cross-env NODE_ICU_DATA=../../node_modules/full-icu ts-node tests/runner", 44 | "test": "yarn run jest && yarn run test262", 45 | "rollup": "rollup -c rollup.config.js", 46 | "compile": "tsc && tsc -p tsconfig.esm.json && tsc -p tsconfig.es6.json && api-extractor run --local" 47 | }, 48 | "bugs": { 49 | "url": "https://github.com/formatjs/formatjs/issues" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/intl-displaynames/polyfill.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill'); 2 | -------------------------------------------------------------------------------- /packages/intl-displaynames/src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import {DisplayNames} from '.'; 2 | 3 | declare global { 4 | // eslint-disable-next-line @typescript-eslint/no-namespace 5 | namespace Intl { 6 | const DisplayNames: DisplayNames; 7 | } 8 | } 9 | 10 | if (!Intl.DisplayNames) { 11 | Object.defineProperty(Intl, 'DisplayNames', { 12 | value: DisplayNames, 13 | enumerable: false, 14 | writable: true, 15 | configurable: true, 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/intl-displaynames/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | import {DisplayNames} from '../src'; 3 | DisplayNames.__addLocaleData( 4 | require('../dist/locale-data/en.json'), 5 | require('../dist/locale-data/zh.json') 6 | ); 7 | 8 | describe('.of()', () => { 9 | it('accepts case-insensitive language code with region subtag', () => { 10 | expect(new DisplayNames('zh', {type: 'language'}).of('zh-hANs-sG')).toBe( 11 | '简体中文(新加坡)' 12 | ); 13 | }); 14 | 15 | it('accepts case-insensitive currency code', () => { 16 | expect( 17 | new DisplayNames('en-US', {type: 'currency', style: 'long'}).of('cNy') 18 | ).toBe('Chinese Yuan'); 19 | }); 20 | 21 | it('preserves unrecognized region subtag in language code when fallback option is code', () => { 22 | expect(new DisplayNames('zh', {fallback: 'code'}).of('zh-Hans-Xy')).toBe( 23 | '简体中文(XY)' 24 | ); 25 | }); 26 | 27 | describe('with fallback set to "none"', () => { 28 | it('returns undefined when called with language code that has unrecognized region subtag', () => { 29 | expect(new DisplayNames('zh', {fallback: 'none'}).of('zh-Hans-XY')).toBe( 30 | undefined 31 | ); 32 | }); 33 | 34 | it('returns undefined when called with language code that valid region subtag but invalid language subtag', () => { 35 | expect(new DisplayNames('zh', {fallback: 'none'}).of('xx-CN')).toBe( 36 | undefined 37 | ); 38 | }); 39 | }); 40 | }); 41 | 42 | // TODO: add snapshot tests 43 | -------------------------------------------------------------------------------- /packages/intl-displaynames/tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "module": "esnext", 6 | "outDir": "dist-es6", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-displaynames/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-displaynames/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "es5", "esnext.intl", "es2017.intl", "es2018.intl"], 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "allowSyntheticDefaultImports": true, 8 | "noFallthroughCasesInSwitch": true, 9 | "types": [ 10 | "babel__core", 11 | "babel__generator", 12 | "babel__template", 13 | "babel__traverse", 14 | "benchmark", 15 | "chai", 16 | "estree", 17 | "fs-extra", 18 | "istanbul-lib-coverage", 19 | "istanbul-lib-report", 20 | "istanbul-reports", 21 | // Don't include mocha here 22 | "jest", 23 | "jest-diff", 24 | "node", 25 | "resolve", 26 | "stack-utils", 27 | "yargs" 28 | ] 29 | }, 30 | "include": ["src/**/*.ts"], 31 | "references": [{"path": "../formatjs-extract-cldr-data"}, {"path": "../intl-utils"}] 32 | } 33 | -------------------------------------------------------------------------------- /packages/intl-format-cache/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .nyc_output 3 | tests/*.js 4 | tests/*.js.map 5 | tests/*.d.ts -------------------------------------------------------------------------------- /packages/intl-format-cache/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oath Inc. 2 | 3 | Licensed under the terms of the New BSD license. See below for terms. 4 | 5 | Redistribution and use of this software in source and binary forms, 6 | with or without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | - Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the 15 | following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | - Neither the name of Oath Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Oath Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /packages/intl-format-cache/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intl-format-cache", 3 | "version": "4.2.25", 4 | "description": "A memoizer factory for Intl format constructors.", 5 | "main": "dist/index.js", 6 | "module": "lib/index.js", 7 | "types": "dist/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "lib", 11 | "src" 12 | ], 13 | "scripts": { 14 | "clean": "rimraf dist lib tests/browser.js tests/browser.js.map *.tsbuildinfo", 15 | "benchmark": "ts-node tests/benchmark", 16 | "build": "tsc && tsc -p tsconfig.esm.json && rollup -c rollup.config.js", 17 | "test": "mocha --opts ../../mocha.opts tests/index.ts" 18 | }, 19 | "devDependencies": { 20 | "@formatjs/intl-pluralrules": "^1.5.6", 21 | "@formatjs/intl-relativetimeformat": "^4.5.13" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "https://github.com/formatjs/formatjs.git" 26 | }, 27 | "keywords": [ 28 | "intl", 29 | "i18n" 30 | ], 31 | "sideEffects": false, 32 | "author": "Eric Ferraiuolo ", 33 | "license": "BSD-3-Clause", 34 | "bugs": { 35 | "url": "https://github.com/formatjs/formatjs/issues" 36 | }, 37 | "homepage": "https://github.com/formatjs/formatjs", 38 | "gitHead": "a7842673d8ad205171ad7c8cb8bb2f318b427c0c" 39 | } 40 | -------------------------------------------------------------------------------- /packages/intl-format-cache/rollup.config.js: -------------------------------------------------------------------------------- 1 | import testRollupConfig from '../../rollup.config'; 2 | 3 | export default testRollupConfig -------------------------------------------------------------------------------- /packages/intl-format-cache/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014, Yahoo! Inc. All rights reserved. 3 | Copyrights licensed under the New BSD License. 4 | See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | // -- Utilities ---------------------------------------------------------------- 8 | 9 | function getCacheId(inputs: any[]) { 10 | return JSON.stringify( 11 | inputs.map(input => 12 | input && typeof input === 'object' ? orderedProps(input) : input 13 | ) 14 | ); 15 | } 16 | 17 | function orderedProps(obj: Record) { 18 | return Object.keys(obj) 19 | .sort() 20 | .map(k => ({[k]: obj[k]})); 21 | } 22 | 23 | export type CacheValue = 24 | | Intl.NumberFormat 25 | | Intl.DateTimeFormat 26 | | Intl.PluralRules 27 | | any; 28 | 29 | export interface MemoizeFormatConstructorFn { 30 | ( 31 | constructor: T, 32 | cache?: Record 33 | ): (...args: ConstructorParameters) => any; 34 | } 35 | 36 | const memoizeFormatConstructor: MemoizeFormatConstructorFn = ( 37 | FormatConstructor: any, 38 | cache: Record = {} 39 | ) => (...args: any[]) => { 40 | const cacheId = getCacheId(args); 41 | let format = cacheId && cache[cacheId]; 42 | if (!format) { 43 | format = new (FormatConstructor as any)(...args); 44 | if (cacheId) { 45 | cache[cacheId] = format; 46 | } 47 | } 48 | 49 | return format; 50 | }; 51 | 52 | export default memoizeFormatConstructor; 53 | -------------------------------------------------------------------------------- /packages/intl-format-cache/src/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "module": "commonjs", 6 | "target": "es5" 7 | }, 8 | "include": ["*.ts"] 9 | } -------------------------------------------------------------------------------- /packages/intl-format-cache/tests/index.ts: -------------------------------------------------------------------------------- 1 | import '@formatjs/intl-pluralrules/polyfill-locales'; 2 | import '@formatjs/intl-relativetimeformat/polyfill-locales'; 3 | import memoizeFormatConstructor from '../src'; 4 | import {expect as chaiExpect} from 'chai'; 5 | 6 | declare var expect: typeof chaiExpect; 7 | 8 | describe('intl-format-cache', function () { 9 | it('has a function as the default export', function () { 10 | expect(memoizeFormatConstructor).to.be.a('function'); 11 | }); 12 | 13 | describe('Intl built-ins', function () { 14 | describe('Intl.DateTimeFormat', function () { 15 | var getDateTimeFormat = memoizeFormatConstructor(Intl.DateTimeFormat); 16 | 17 | it('memoizes Intl.DateTimeFormat', function () { 18 | var df = getDateTimeFormat('en'); 19 | 20 | expect(df.resolvedOptions().locale).to.equal('en'); 21 | // Lack of tz support, so just check that it returns a string. 22 | expect(df.format(0)).to.be.a('string'); 23 | 24 | expect(getDateTimeFormat('en')).to.equal(df); 25 | expect(getDateTimeFormat('en', {year: 'numeric'})).not.to.equal(df); 26 | }); 27 | }); 28 | 29 | describe('Intl.NumberFormat', function () { 30 | var getNumberFormat = memoizeFormatConstructor(Intl.NumberFormat); 31 | 32 | it('memoizes Intl.NumberFormat', function () { 33 | var nf = getNumberFormat('en'); 34 | 35 | expect(nf.resolvedOptions().locale).to.equal('en'); 36 | expect(nf.format(1000)).to.equal('1,000'); 37 | 38 | expect(getNumberFormat('en')).to.equal(nf); 39 | expect(getNumberFormat('en', {style: 'percent'})).not.to.equal(nf); 40 | }); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /packages/intl-format-cache/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-format-cache/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | }, 7 | "include": ["src"], 8 | "references": [{"path": "../intl-pluralrules"}, {"path": "../intl-relativetimeformat"}] 9 | } 10 | -------------------------------------------------------------------------------- /packages/intl-listformat/.gitignore: -------------------------------------------------------------------------------- 1 | .nyc_output 2 | lib 3 | node_modules/ 4 | tests/browser.* 5 | src/locales.ts 6 | src/en.ts 7 | tests/polyfill-all.js 8 | -------------------------------------------------------------------------------- /packages/intl-listformat/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/intl-listformat/README.md: -------------------------------------------------------------------------------- 1 | # Intl ListFormat 2 | 3 | We've migrated the README to [here](../../website/docs/polyfills/intl-listformat.md). 4 | -------------------------------------------------------------------------------- /packages/intl-listformat/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-listformat/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/intl-listformat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/intl-listformat", 3 | "version": "1.4.5", 4 | "description": "Formats JS list in a i18n-safe way", 5 | "keywords": [ 6 | "intl", 7 | "i18n", 8 | "list", 9 | "format", 10 | "formatjs" 11 | ], 12 | "author": "Long Ho ", 13 | "bugs": { 14 | "url": "https://github.com/formatjs/formatjs/issues" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git@github.com:formatjs/formatjs.git" 19 | }, 20 | "devDependencies": { 21 | "formatjs-extract-cldr-data": "^10.1.5" 22 | }, 23 | "dependencies": { 24 | "@formatjs/intl-utils": "^2.2.3" 25 | }, 26 | "main": "dist/index.js", 27 | "module": "lib/index.js", 28 | "types": "lib/intl-listformat.d.ts", 29 | "files": [ 30 | "dist-es6", 31 | "dist", 32 | "lib", 33 | "polyfill-locales.js", 34 | "polyfill.js", 35 | "src" 36 | ], 37 | "scripts": { 38 | "build": "yarn run cldr && yarn run compile", 39 | "cldr": "ts-node scripts/cldr", 40 | "clean": "rimraf dist lib dist-es6 dist-es6 *.tsbuildinfo", 41 | "compile": "tsc && tsc -p tsconfig.esm.json && tsc -p tsconfig.es6.json && api-extractor run --local && rollup -c rollup.config.js", 42 | "jest": "cross-env NODE_ICU_DATA=../../node_modules/full-icu NODE_ENV=test jest", 43 | "test": "yarn run jest && cross-env NODE_ICU_DATA=../../node_modules/full-icu ts-node tests/runner" 44 | }, 45 | "homepage": "https://github.com/formatjs/formatjs", 46 | "license": "MIT", 47 | "gitHead": "a7842673d8ad205171ad7c8cb8bb2f318b427c0c" 48 | } 49 | -------------------------------------------------------------------------------- /packages/intl-listformat/polyfill-locales.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill-locales') -------------------------------------------------------------------------------- /packages/intl-listformat/polyfill.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill') -------------------------------------------------------------------------------- /packages/intl-listformat/src/index.ts: -------------------------------------------------------------------------------- 1 | import IntlListFormat from './core'; 2 | export * from './core'; 3 | export default IntlListFormat; 4 | -------------------------------------------------------------------------------- /packages/intl-listformat/src/polyfill-locales.ts: -------------------------------------------------------------------------------- 1 | import './polyfill'; 2 | import './locales'; 3 | -------------------------------------------------------------------------------- /packages/intl-listformat/src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import ListFormat from './core'; 2 | if (!('ListFormat' in Intl)) { 3 | Object.defineProperty(Intl, 'ListFormat', { 4 | value: ListFormat, 5 | writable: true, 6 | enumerable: false, 7 | configurable: true, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /packages/intl-listformat/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import '../src/polyfill'; 2 | import '../polyfill'; 3 | import '../dist/locale-data/zh'; 4 | import '../dist/locale-data/en'; 5 | import PolyfilledListFormat from '../src/core'; 6 | 7 | describe('Intl.ListFormat', function () { 8 | const ListFormat: typeof PolyfilledListFormat = (Intl as any).ListFormat; 9 | it('should support aliases', function () { 10 | expect( 11 | new ListFormat('zh-CN', {type: 'unit'}).format(['1', '2', '3']) 12 | ).toBe('123'); 13 | expect(new ListFormat('zh-CN', {type: 'unit'}).format(['1', '2'])).toBe( 14 | '12' 15 | ); 16 | expect( 17 | new ListFormat('zh-TW', {type: 'unit'}).format(['1', '2', '3']) 18 | ).toBe('1 2 3'); 19 | expect(new ListFormat('zh-TW', {type: 'unit'}).format(['1', '2'])).toBe( 20 | '1 2' 21 | ); 22 | }); 23 | it('should resolve parent correctly', function () { 24 | expect(new ListFormat('en-AI').format(['1', '2'])).toBe('1 and 2'); 25 | // Node 12 has an old version of CLDR 26 | if (process.version.startsWith('v10')) { 27 | expect(new ListFormat('en-AI').format(['1', '2', '3'])).toBe( 28 | '1, 2 and 3' 29 | ); 30 | } 31 | }); 32 | it('should normalize case correctly', function () { 33 | const lf = new ListFormat('en-us', {style: 'short', type: 'unit'}); 34 | expect(lf.resolvedOptions()).toEqual({ 35 | locale: 'en-US', 36 | type: 'unit', 37 | style: 'short', 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /packages/intl-listformat/tests/supported-locales-of.test.ts: -------------------------------------------------------------------------------- 1 | import '../src/polyfill'; 2 | import '../polyfill'; 3 | import '../dist/locale-data/zh'; 4 | 5 | describe('supportedLocalesOf', function () { 6 | const ListFormat = (Intl as any).ListFormat; 7 | function test() { 8 | expect(ListFormat.supportedLocalesOf(['zh', 'en-jj'])).toContain('zh'); 9 | expect(ListFormat.supportedLocalesOf('fr')).toEqual([]); 10 | } 11 | if (ListFormat.polyfilled) { 12 | it('should return correct locales that we only have data for', test); 13 | } else { 14 | it.skip('should return correct locales that we only have data for', test); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /packages/intl-listformat/tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "module": "esnext", 6 | "outDir": "dist-es6" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-listformat/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-listformat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "es5", "esnext.intl", "es2017.intl", "es2018.intl"], 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "types": [ 8 | "babel__core", 9 | "babel__generator", 10 | "babel__template", 11 | "babel__traverse", 12 | "benchmark", 13 | "chai", 14 | "estree", 15 | "fs-extra", 16 | "istanbul-lib-coverage", 17 | "istanbul-lib-report", 18 | "istanbul-reports", 19 | // Don't include mocha here 20 | "jest", 21 | "jest-diff", 22 | "node", 23 | "resolve", 24 | "stack-utils", 25 | "yargs" 26 | ], 27 | }, 28 | "include": ["src"], 29 | "references": [{"path": "../formatjs-extract-cldr-data"}, {"path": "../intl-utils"}] 30 | } 31 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/.gitignore: -------------------------------------------------------------------------------- 1 | index.d.ts 2 | *.map 3 | lib -------------------------------------------------------------------------------- /packages/intl-locales-supported/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oath Inc. 2 | 3 | Licensed under the terms of the New BSD license. See below for terms. 4 | 5 | Redistribution and use of this software in source and binary forms, 6 | with or without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | - Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the 15 | following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | - Neither the name of Oath Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Oath Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/README.md: -------------------------------------------------------------------------------- 1 | # intl-locales-supported 2 | 3 | Utility to help you determine if your runtime has modern Intl API & locales support. This specifically checks for `Intl.NumberFormat`, `Intl.PluralRules` & `Intl.RelativeTimeFormat` and is being used by `react-intl`. 4 | 5 | [![npm Version](https://badgen.net/npm/v/intl-locales-supported)](https://www.npmjs.org/package/intl-locales-supported) 6 | ![size](https://badgen.net/bundlephobia/minzip/intl-locales-supported) 7 | 8 | ## Usage 9 | 10 | ```js 11 | const areIntlLocalesSupported = require('intl-locales-supported'); 12 | 13 | const localesMyAppSupports = [ 14 | /* list locales here */ 15 | ]; 16 | 17 | // Determine if the built-in `Intl` has the locale data we need. 18 | if ( 19 | !areIntlLocalesSupported(localesMyAppSupports, [ 20 | Intl.PluralRules, 21 | Intl.RelativeTimeFormat, 22 | ]) 23 | ) { 24 | // `Intl` exists, but it doesn't have the data we need, so load the 25 | // polyfill and replace the constructors we need with the polyfill's. 26 | require('@formatjs/intl-pluralrules/polyfill'); 27 | require('@formatjs/intl-pluralrules/dist/locale-data/de'); // Load de 28 | 29 | require('@formatjs/intl-relativetimeformat/polyfill'); 30 | require('@formatjs/intl-relativetimeformat/dist/locale-data/de'); // Load de 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intl-locales-supported", 3 | "version": "1.8.6", 4 | "description": "Utility to help you polyfill the Node.js runtime when the Intl APIs are missing, or if the built-in Intl is missing locale data that you need.", 5 | "main": "dist/index.js", 6 | "module": "lib/index.js", 7 | "types": "dist/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "lib", 11 | "src" 12 | ], 13 | "author": "Eric Ferraiuolo ", 14 | "license": "BSD-3-Clause", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/formatjs/formatjs.git" 18 | }, 19 | "keywords": [ 20 | "i18n", 21 | "intl", 22 | "internationalization", 23 | "localization", 24 | "globalization" 25 | ], 26 | "bugs": { 27 | "url": "https://github.com/formatjs/formatjs/issues" 28 | }, 29 | "sideEffects": false, 30 | "homepage": "https://github.com/formatjs/formatjs", 31 | "scripts": { 32 | "clean": "rimraf dist lib *.tsbuildinfo", 33 | "build": "tsc && tsc -p tsconfig.esm.json", 34 | "test": "cross-env NODE_ICU_DATA=../../node_modules/full-icu mocha --opts ../../mocha.opts tests/index.ts" 35 | }, 36 | "gitHead": "a7842673d8ad205171ad7c8cb8bb2f318b427c0c" 37 | } 38 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015, Yahoo Inc. 3 | * Copyrights licensed under the New BSD License. 4 | * See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | type IntlConstructor = { 8 | supportedLocalesOf(locales: string | string[], options?: any): string[]; 9 | }; 10 | 11 | export default function areIntlLocalesSupported( 12 | locales: string | string[], 13 | constructorsToCheck?: Array 14 | ): boolean { 15 | if (typeof Intl === 'undefined') { 16 | return false; 17 | } 18 | 19 | if (!locales) { 20 | throw new Error('locales must be supplied.'); 21 | } 22 | 23 | if (!Array.isArray(locales)) { 24 | locales = [locales]; 25 | } 26 | 27 | let intlConstructors = constructorsToCheck || [ 28 | Intl.DateTimeFormat, 29 | Intl.NumberFormat, 30 | Intl.PluralRules, 31 | ]; 32 | 33 | intlConstructors = intlConstructors.filter(Boolean); 34 | 35 | if ( 36 | intlConstructors.length === 0 || 37 | (constructorsToCheck && 38 | intlConstructors.length !== constructorsToCheck.length) 39 | ) { 40 | return false; 41 | } 42 | 43 | return intlConstructors.every( 44 | intlConstructor => 45 | intlConstructor.supportedLocalesOf(locales).length === locales.length 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/tests/index.ts: -------------------------------------------------------------------------------- 1 | import areIntlLocalesSupported from '../src'; 2 | import {expect as chaiExpect} from 'chai'; 3 | 4 | declare var expect: typeof chaiExpect; 5 | 6 | describe('exports', function () { 7 | it('should have a default export function', function () { 8 | expect(areIntlLocalesSupported).to.be.a('function'); 9 | }); 10 | }); 11 | 12 | describe('areIntlLocalesSupported()', function () { 13 | const Intl = global.Intl; 14 | 15 | describe('missing Intl', function () { 16 | beforeEach(function () { 17 | global.Intl = undefined as any; 18 | }); 19 | 20 | afterEach(function () { 21 | global.Intl = Intl; 22 | }); 23 | 24 | it('should return `false` for "en"', function () { 25 | expect(areIntlLocalesSupported('en')).to.be.false; 26 | }); 27 | }); 28 | 29 | describe('polyfill', function () { 30 | const NumberFormat = global.Intl.NumberFormat; 31 | beforeEach(function () { 32 | global.Intl.NumberFormat = { 33 | supportedLocalesOf() { 34 | return []; 35 | }, 36 | } as any; 37 | }); 38 | 39 | afterEach(function () { 40 | global.Intl.NumberFormat = NumberFormat; 41 | }); 42 | 43 | it('should return `true` for "en" after polyfill', function () { 44 | expect(areIntlLocalesSupported('en')).to.be.false; 45 | global.Intl.NumberFormat = NumberFormat; 46 | expect(areIntlLocalesSupported('en')).to.be.true; 47 | }); 48 | }); 49 | 50 | it('should return `true` for "en"', function () { 51 | expect(areIntlLocalesSupported('en')).to.be.true; 52 | }); 53 | 54 | it('should return `true` for "fr"', function () { 55 | expect(areIntlLocalesSupported('fr')).to.be.true; 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-locales-supported/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"], 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/.gitignore: -------------------------------------------------------------------------------- 1 | src/parser.ts 2 | src/parser.js -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oath Inc. 2 | 3 | Licensed under the terms of the New BSD license. See below for terms. 4 | 5 | Redistribution and use of this software in source and binary forms, 6 | with or without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | - Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the 15 | following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | - Neither the name of Oath Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Oath Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/README.md: -------------------------------------------------------------------------------- 1 | # Intl MessageFormat Parser 2 | 3 | We've migrated the README to [here](../../website/docs/intl-messageformat-parser.md). 4 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "intl-messageformat-parser", 3 | "version": "5.0.1", 4 | "description": "Parses ICU Message strings into an AST via JavaScript.", 5 | "main": "dist/index.js", 6 | "module": "lib/index.js", 7 | "types": "lib/intl-messageformat-parser.d.ts", 8 | "files": [ 9 | "dist", 10 | "lib", 11 | "src" 12 | ], 13 | "scripts": { 14 | "clean": "rimraf dist lib *.tsbuildinfo", 15 | "build": "node build.js && tsc && tsc -p tsconfig.esm.json && api-extractor run --local && rollup -c rollup.config.js", 16 | "benchmark": "node ./test/benchmark.js", 17 | "test": "cross-env NODE_ENV=test jest" 18 | }, 19 | "contributors": [ 20 | "Eric Ferraiuolo ", 21 | "Long Ho ", 22 | "Ryuichi Okumura ", 23 | "Seth Bertalotto ", 24 | "Song Seunggeun ", 25 | "Tobias Bieniek " 26 | ], 27 | "repository": { 28 | "type": "git", 29 | "url": "git://github.com/formatjs/formatjs.git" 30 | }, 31 | "keywords": [ 32 | "i18n", 33 | "intl", 34 | "internationalization", 35 | "localization", 36 | "globalization", 37 | "messageformat", 38 | "parser", 39 | "plural", 40 | "icu" 41 | ], 42 | "sideEffects": false, 43 | "author": "Eric Ferraiuolo ", 44 | "license": "BSD-3-Clause", 45 | "bugs": { 46 | "url": "https://github.com/formatjs/formatjs/issues" 47 | }, 48 | "dependencies": { 49 | "@formatjs/intl-unified-numberformat": "^3.3.4" 50 | }, 51 | "homepage": "https://github.com/formatjs/formatjs", 52 | "gitHead": "8b0baec8eda5002715cf893274fe59782fc2d371" 53 | } 54 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { uglify } from 'rollup-plugin-uglify'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | 4 | const resolveConfig = resolve({ 5 | mainFields: ['module', 'main'] 6 | }); 7 | const uglifyConfig = uglify(); 8 | export default [ 9 | { 10 | input: './lib/index.js', 11 | output: { 12 | sourcemap: true, 13 | file: 'dist/umd/intl-messageformat-parser.js', 14 | format: 'umd', 15 | exports: 'named', 16 | name: 'IntlMessageFormatParser' 17 | }, 18 | plugins: [resolveConfig] 19 | }, 20 | { 21 | input: './lib/index.js', 22 | output: { 23 | sourcemap: true, 24 | file: 'dist/umd/intl-messageformat-parser.min.js', 25 | format: 'umd', 26 | exports: 'named', 27 | name: 'IntlMessageFormatParser' 28 | }, 29 | plugins: [resolveConfig, uglifyConfig] 30 | } 31 | ]; -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/src/index.ts: -------------------------------------------------------------------------------- 1 | import {pegParse, IParseOptions} from './parser'; 2 | import {Options, MessageFormatElement} from './types'; 3 | import {normalizeHashtagInPlural} from './normalize'; 4 | export * from './types'; 5 | export * from './parser'; 6 | export * from './skeleton'; 7 | 8 | export type ParseOptions = Options & IParseOptions; 9 | 10 | export function parse( 11 | input: string, 12 | opts?: ParseOptions 13 | ): MessageFormatElement[] { 14 | const els = pegParse(input, opts); 15 | if (!opts || opts.normalizeHashtagInPlural !== false) { 16 | normalizeHashtagInPlural(els); 17 | } 18 | return els; 19 | } 20 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/src/normalize.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MessageFormatElement, 3 | isPluralElement, 4 | isLiteralElement, 5 | LiteralElement, 6 | isSelectElement, 7 | } from './types'; 8 | import {pegParse} from './parser'; 9 | 10 | const PLURAL_HASHTAG_REGEX = /(^|[^\\])#/g; 11 | 12 | /** 13 | * Whether to convert `#` in plural rule options 14 | * to `{var, number}` 15 | * @param el AST Element 16 | * @param pluralStack current plural stack 17 | */ 18 | export function normalizeHashtagInPlural(els: MessageFormatElement[]) { 19 | els.forEach(el => { 20 | // If we're encountering a plural el 21 | if (!isPluralElement(el) && !isSelectElement(el)) { 22 | return; 23 | } 24 | // Go down the options and search for # in any literal element 25 | Object.keys(el.options).forEach(id => { 26 | const opt = el.options[id]; 27 | // If we got a match, we have to split this 28 | // and inject a NumberElement in the middle 29 | let matchingLiteralElIndex = -1; 30 | let literalEl: LiteralElement | undefined = undefined; 31 | for (let i = 0; i < opt.value.length; i++) { 32 | const el = opt.value[i] as LiteralElement; 33 | if (isLiteralElement(el) && PLURAL_HASHTAG_REGEX.test(el.value)) { 34 | matchingLiteralElIndex = i; 35 | literalEl = el; 36 | break; 37 | } 38 | } 39 | 40 | if (literalEl) { 41 | const newValue = literalEl.value.replace( 42 | PLURAL_HASHTAG_REGEX, 43 | `$1{${el.value}, number}` 44 | ); 45 | const newEls = pegParse(newValue); 46 | opt.value.splice(matchingLiteralElIndex, 1, ...newEls); 47 | } 48 | normalizeHashtagInPlural(opt.value); 49 | }); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/__snapshots__/none_arg.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`trivial 1`] = ` 4 | Array [ 5 | Object { 6 | "type": 1, 7 | "value": "0", 8 | }, 9 | ] 10 | `; 11 | 12 | exports[`trivial 2`] = ` 13 | Array [ 14 | Object { 15 | "type": 1, 16 | "value": "arg", 17 | }, 18 | ] 19 | `; 20 | 21 | exports[`trivial 3`] = ` 22 | Array [ 23 | Object { 24 | "type": 0, 25 | "value": "hello ", 26 | }, 27 | Object { 28 | "type": 1, 29 | "value": "name", 30 | }, 31 | ] 32 | `; 33 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/__snapshots__/plural_arg.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`escaped nested message 1`] = ` 4 | Array [ 5 | Object { 6 | "type": 0, 7 | "value": " ", 8 | }, 9 | Object { 10 | "offset": 0, 11 | "options": Object { 12 | "one": Object { 13 | "location": undefined, 14 | "value": Array [ 15 | Object { 16 | "type": 0, 17 | "value": "item}", 18 | }, 19 | ], 20 | }, 21 | "other": Object { 22 | "location": undefined, 23 | "value": Array [ 24 | Object { 25 | "type": 0, 26 | "value": "items}", 27 | }, 28 | ], 29 | }, 30 | }, 31 | "pluralType": "cardinal", 32 | "type": 6, 33 | "value": "itemCount", 34 | }, 35 | ] 36 | `; 37 | 38 | exports[`trivial 1`] = ` 39 | Array [ 40 | Object { 41 | "type": 0, 42 | "value": " Cart: ", 43 | }, 44 | Object { 45 | "type": 1, 46 | "value": "itemCount", 47 | }, 48 | Object { 49 | "type": 0, 50 | "value": " ", 51 | }, 52 | Object { 53 | "offset": 0, 54 | "options": Object { 55 | "one": Object { 56 | "location": undefined, 57 | "value": Array [ 58 | Object { 59 | "type": 0, 60 | "value": "item", 61 | }, 62 | ], 63 | }, 64 | "other": Object { 65 | "location": undefined, 66 | "value": Array [ 67 | Object { 68 | "type": 0, 69 | "value": "items", 70 | }, 71 | ], 72 | }, 73 | }, 74 | "pluralType": "cardinal", 75 | "type": 6, 76 | "value": "itemCount", 77 | }, 78 | ] 79 | `; 80 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/__snapshots__/simple_arg.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`date & time arg 1`] = ` 4 | Array [ 5 | Object { 6 | "type": 0, 7 | "value": "Your meeting is scheduled for the ", 8 | }, 9 | Object { 10 | "style": null, 11 | "type": 3, 12 | "value": "dateVal", 13 | }, 14 | Object { 15 | "type": 0, 16 | "value": " at ", 17 | }, 18 | Object { 19 | "style": null, 20 | "type": 4, 21 | "value": "timeVal", 22 | }, 23 | ] 24 | `; 25 | 26 | exports[`date & time arg with style 1`] = ` 27 | Array [ 28 | Object { 29 | "type": 0, 30 | "value": "Your meeting is scheduled for the ", 31 | }, 32 | Object { 33 | "style": "long", 34 | "type": 3, 35 | "value": "dateVal", 36 | }, 37 | Object { 38 | "type": 0, 39 | "value": " at ", 40 | }, 41 | Object { 42 | "style": "short", 43 | "type": 4, 44 | "value": "timeVal", 45 | }, 46 | ] 47 | `; 48 | 49 | exports[`number arg 1`] = ` 50 | Array [ 51 | Object { 52 | "type": 0, 53 | "value": "I have ", 54 | }, 55 | Object { 56 | "style": null, 57 | "type": 2, 58 | "value": "numCats", 59 | }, 60 | Object { 61 | "type": 0, 62 | "value": " cats.", 63 | }, 64 | ] 65 | `; 66 | 67 | exports[`number arg with style 1`] = ` 68 | Array [ 69 | Object { 70 | "type": 0, 71 | "value": "Almost ", 72 | }, 73 | Object { 74 | "style": "percent", 75 | "type": 2, 76 | "value": "pctBlack", 77 | }, 78 | Object { 79 | "type": 0, 80 | "value": " of them are black.", 81 | }, 82 | ] 83 | `; 84 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/arg_style.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | import {printAST} from '../src/printer'; 3 | 4 | test.each([ 5 | `{0,date,y-M-d HH:mm:ss}`, 6 | `{0,number,y-M-d HH:mm:ss}`, 7 | `{0,date,y-M-d HH:mm:ss zzzz}`, 8 | `{0,number,y-M-d HH:mm:ss zzzz}`, 9 | `{0,date,y-M-d,HH:mm:ss,zzzz}`, 10 | `{0,number,y-M-d,HH:mm:ss,zzzz}`, 11 | `{0,number,'{}'}`, 12 | `{0,number,''}`, 13 | ])('argStyleText test case: %p', testCase => { 14 | const ast = pegParse(testCase); 15 | expect(ast).toMatchSnapshot(); 16 | expect(printAST(ast)).toMatchSnapshot(); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/date_skeleton.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | import {printAST} from '../src/printer'; 3 | import {parseDateTimeSkeleton} from '../src/skeleton'; 4 | 5 | test.each([ 6 | `yyyy.MM.dd G 'at' HH:mm:ss vvvv`, 7 | `EEE, MMM d, ''yy`, 8 | `h:mm a`, 9 | ``, 10 | ])('case: %p', skeleton => { 11 | const ast = pegParse(`{0, date, ::${skeleton}}`); 12 | expect(ast).toMatchSnapshot(); 13 | expect(printAST(ast)).toMatchSnapshot(); 14 | }); 15 | 16 | test.each([ 17 | `yyyy.MM.dd G 'at' HH:mm:ss zzzz`, 18 | `EEE, MMM d, ''yy`, 19 | `h:mm a`, 20 | ``, 21 | ])('case: %p', skeleton => { 22 | expect(parseDateTimeSkeleton(skeleton)).toMatchSnapshot(); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/error.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src'; 2 | describe('error', function () { 3 | [ 4 | 'You have {count, plural, one {# hot dog} one {# hamburger} one {# sandwich} other {# snacks}} in your lunch bag.', 5 | 'You have {count, select, one {# hot dog} one {# hamburger} one {# sandwich} other {# snacks}} in your lunch bag.', 6 | ].forEach(mess => { 7 | it(`show throw SyntaxError '${mess}'`, function () { 8 | expect(() => pegParse(mess)).toThrowError(/Duplicate/); 9 | }); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/nested.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | 3 | test('plural arg nested inside select arg', () => { 4 | expect( 5 | pegParse(`\ 6 | {gender_of_host, select, 7 | female { 8 | {num_guests, plural, offset:1 9 | =0 {{host} does not give a party.} 10 | =1 {{host} invites {guest} to her party.} 11 | =2 {{host} invites {guest} and one other person to her party.} 12 | other {{host} invites {guest} and # other people to her party.}}} 13 | male { 14 | {num_guests, plural, offset:1 15 | =0 {{host} does not give a party.} 16 | =1 {{host} invites {guest} to his party.} 17 | =2 {{host} invites {guest} and one other person to his party.} 18 | other {{host} invites {guest} and # other people to his party.}}} 19 | other { 20 | {num_guests, plural, offset:1 21 | =0 {{host} does not give a party.} 22 | =1 {{host} invites {guest} to their party.} 23 | =2 {{host} invites {guest} and one other person to their party.} 24 | other {{host} invites {guest} and # other people to their party.}}}}`) 25 | ).toMatchSnapshot(); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/none_arg.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | 3 | test('trivial', () => { 4 | expect(pegParse('{0}')).toMatchSnapshot(); 5 | expect(pegParse('{arg}')).toMatchSnapshot(); 6 | expect(pegParse('hello {name}')).toMatchSnapshot(); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/number_skeleton.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | import {printAST} from '../src/printer'; 3 | import {isNumberElement, TYPE, isNumberSkeleton} from '../src/types'; 4 | import {convertNumberSkeletonToNumberFormatOptions} from '../src/skeleton'; 5 | 6 | test.each([ 7 | `compact-short currency/GBP`, 8 | `@@#`, 9 | `currency/CAD unit-width-narrow`, 10 | ])('case: %p', skeleton => { 11 | const ast = pegParse(`{0, number, ::${skeleton}}`); 12 | expect(ast).toMatchSnapshot(); 13 | expect(printAST(ast)).toMatchSnapshot(); 14 | }); 15 | 16 | test.each([ 17 | 'percent .##', 18 | 'percent .000*', 19 | 'percent .0###', 20 | 'percent .00/@##', 21 | 'percent .00/@@@', 22 | 'percent .00/@@@@*', 23 | 'currency/CAD .', 24 | 'currency/GBP .0*/@@@', 25 | 'currency/GBP .00##/@@@', 26 | 'currency/GBP .00##/@@@ unit-width-full-name', 27 | 'measure-unit/length-meter .00##/@@@', 28 | 'measure-unit/length-meter .00##/@@@ unit-width-full-name', 29 | 'compact-short', 30 | 'compact-long', 31 | 'scientific', 32 | 'scientific/sign-always', 33 | 'scientific/+ee/sign-always', 34 | 'engineering', 35 | 'engineering/sign-except-zero', 36 | 'notation-simple', 37 | 'sign-auto', 38 | 'sign-always', 39 | 'sign-never', 40 | 'sign-accounting', 41 | 'sign-accounting-always', 42 | 'sign-except-zero', 43 | 'sign-accounting-except-zero', 44 | ])('[convertNumberSkeletonToNumberFormatOptions] case: %p', skeleton => { 45 | const ast = pegParse(`{0, number, ::${skeleton}}`); 46 | const el = ast[0]; 47 | if (!isNumberElement(el)) { 48 | throw expect(el.type).toEqual(TYPE.number); 49 | } 50 | if (!isNumberSkeleton(el.style)) { 51 | throw 'element style should be parsed as number skeleton'; 52 | } 53 | expect( 54 | convertNumberSkeletonToNumberFormatOptions(el.style.tokens) 55 | ).toMatchSnapshot(); 56 | }); 57 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/plural_arg.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | 3 | test('trivial', () => { 4 | expect( 5 | pegParse(`\ 6 | Cart: {itemCount} {itemCount, plural, 7 | one {item} 8 | other {items} 9 | }`) 10 | ).toMatchSnapshot(); 11 | expect( 12 | pegParse(`\ 13 | You have {itemCount, plural, 14 | =0 {no items} 15 | one {1 item} 16 | other {{itemCount} items} 17 | }.`) 18 | ); 19 | }); 20 | 21 | test('escaped nested message', () => { 22 | expect( 23 | pegParse(`\ 24 | {itemCount, plural, 25 | one {item'}'} 26 | other {items'}'} 27 | }`) 28 | ).toMatchSnapshot(); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/select_arg.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | 3 | test('trivial', () => { 4 | expect( 5 | pegParse(`\ 6 | {gender, select, 7 | male {He} 8 | female {She} 9 | other {They} 10 | } will respond shortly. 11 | `) 12 | ).toMatchSnapshot(); 13 | }); 14 | 15 | test('nested arguments', () => { 16 | expect( 17 | pegParse(`\ 18 | {taxableArea, select, 19 | yes {An additional {taxRate, number, percent} tax will be collected.} 20 | other {No taxes apply.} 21 | } 22 | `) 23 | ).toMatchSnapshot(); 24 | }); 25 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/simple_arg.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | 3 | test('number arg', () => { 4 | expect(pegParse('I have {numCats, number} cats.')).toMatchSnapshot(); 5 | }); 6 | 7 | test('number arg with style', () => { 8 | expect( 9 | pegParse('Almost {pctBlack, number, percent} of them are black.') 10 | ).toMatchSnapshot(); 11 | }); 12 | 13 | test('date & time arg', () => { 14 | expect( 15 | pegParse( 16 | 'Your meeting is scheduled for the {dateVal, date} at {timeVal, time}' 17 | ) 18 | ).toMatchSnapshot(); 19 | }); 20 | 21 | test('date & time arg with style', () => { 22 | expect( 23 | pegParse( 24 | 'Your meeting is scheduled for the {dateVal, date, long} at {timeVal, time, short}' 25 | ) 26 | ).toMatchSnapshot(); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/tag.test.ts: -------------------------------------------------------------------------------- 1 | import {pegParse} from '../src/parser'; 2 | 3 | test('tag with number arg', () => { 4 | expect( 5 | pegParse('I have {numCats, number} cats.') 6 | ).toMatchSnapshot(); 7 | }); 8 | 9 | test('tag with rich arg', () => { 10 | expect( 11 | pegParse( 12 | 'I have {numCats, number} some string {placeholder} cats.' 13 | ) 14 | ).toMatchSnapshot(); 15 | }); 16 | 17 | test('escaped tag with rich arg', () => { 18 | expect(pegParse("I '<3 cats.")).toMatchSnapshot(); 19 | }); 20 | 21 | test('escaped multiple tags', () => { 22 | expect(pegParse("I '<'3 cats. 'foo' 'bar'")).toMatchSnapshot(); 23 | }); 24 | 25 | test('escaped multiple tags with placeholder', () => { 26 | expect( 27 | pegParse("I '<'3 cats. 'foo' ''{bar}''") 28 | ).toMatchSnapshot(); 29 | }); 30 | 31 | test('mismatched tag', function () { 32 | expect(() => pegParse('this is mismatch')).toThrowError(/Mismatch/); 33 | }); 34 | 35 | test('nested tag', function () { 36 | expect( 37 | pegParse('this is nested {placeholder}') 38 | ).toMatchSnapshot(); 39 | }); 40 | 41 | test('self-closing tag', function () { 42 | expect( 43 | pegParse('this is
nested {placeholder}') 44 | ).toMatchSnapshot(); 45 | }); 46 | 47 | test('tag with dash', function () { 48 | expect( 49 | pegParse('this is
nested {placeholder}') 50 | ).toMatchSnapshot(); 51 | }); 52 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/test/unicode_whitespace.test.ts: -------------------------------------------------------------------------------- 1 | import {parse, TYPE, SelectElement} from '../src'; 2 | 3 | test('it skips unicode no-break space (U+00A0)', () => { 4 | const tree = parse(`{gender, select, 5 | \u00a0male { 6 | {He}} 7 | \u00a0female { 8 | {She}} 9 | \u00a0other{ 10 | {They}}} 11 | `); 12 | const selectElement = tree[0] as SelectElement; 13 | expect(selectElement.type).toBe(TYPE.select); 14 | expect(Object.keys(selectElement.options)).toEqual([ 15 | 'male', 16 | 'female', 17 | 'other', 18 | ]); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext", 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-messageformat-parser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "baseUrl": ".", 7 | "noImplicitAny": false, 8 | "noUnusedLocals": false, // Bc of parser.ts 9 | "noUnusedParameters": false, // Bc of parser.ts 10 | "types": [ 11 | "benchmark", 12 | "chai", 13 | "estree", 14 | "fs-extra", 15 | "istanbul-lib-coverage", 16 | "istanbul-lib-report", 17 | "istanbul-reports", 18 | // Don't include mocha here 19 | "jest", 20 | "jest-diff", 21 | "node", 22 | "resolve", 23 | "stack-utils", 24 | "yargs" 25 | ] 26 | }, 27 | "include": ["src"], 28 | "references": [{"path": "../intl-unified-numberformat"}] 29 | } 30 | -------------------------------------------------------------------------------- /packages/intl-messageformat/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | tests/*.js* 3 | !tests/tsconfig.json 4 | .tsbuildinfo 5 | core.js 6 | core.d.ts 7 | !tests/setup.js 8 | .rpt2_cache 9 | -------------------------------------------------------------------------------- /packages/intl-messageformat/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | scripts/ 3 | test/ 4 | tests/ 5 | *.log 6 | .rpt2_cache 7 | coverage 8 | *.config.js 9 | tsconfig.* 10 | .nyc_output 11 | *.d.ts.map 12 | -------------------------------------------------------------------------------- /packages/intl-messageformat/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019, Oath Inc. 2 | 3 | Licensed under the terms of the New BSD license. See below for terms. 4 | 5 | Redistribution and use of this software in source and binary forms, 6 | with or without modification, are permitted provided that the following 7 | conditions are met: 8 | 9 | - Redistributions of source code must retain the above 10 | copyright notice, this list of conditions and the 11 | following disclaimer. 12 | 13 | - Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the 15 | following disclaimer in the documentation and/or other 16 | materials provided with the distribution. 17 | 18 | - Neither the name of Oath Inc. nor the names of its 19 | contributors may be used to endorse or promote products 20 | derived from this software without specific prior 21 | written permission of Oath Inc. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 24 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 25 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 26 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /packages/intl-messageformat/README.md: -------------------------------------------------------------------------------- 1 | # Intl MessageFormat 2 | 3 | We've migrated the README to [here](../../website/docs/intl-messageformat.md). 4 | -------------------------------------------------------------------------------- /packages/intl-messageformat/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-messageformat/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { uglify } from 'rollup-plugin-uglify'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | import testRollupConfig from '../../rollup.config' 4 | 5 | const resolveConfig = resolve({ 6 | mainFields: ['module', 'main'] 7 | }); 8 | const uglifyConfig = uglify(); 9 | export default [ 10 | { 11 | input: './lib/index.js', 12 | output: { 13 | sourcemap: true, 14 | file: 'dist/umd/intl-messageformat.js', 15 | format: 'umd', 16 | name: 'IntlMessageFormat' 17 | }, 18 | plugins: [resolveConfig] 19 | }, 20 | { 21 | input: './lib/index.js', 22 | output: { 23 | sourcemap: true, 24 | file: 'dist/umd/intl-messageformat.min.js', 25 | format: 'umd', 26 | name: 'IntlMessageFormat' 27 | }, 28 | plugins: [resolveConfig, uglifyConfig] 29 | }, 30 | ...testRollupConfig 31 | ]; -------------------------------------------------------------------------------- /packages/intl-messageformat/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2014, Yahoo! Inc. All rights reserved. 3 | Copyrights licensed under the New BSD License. 4 | See the accompanying LICENSE file for terms. 5 | */ 6 | 7 | import IntlMessageFormat from './core'; 8 | export * from './formatters'; 9 | export * from './core'; 10 | export * from './error'; 11 | export default IntlMessageFormat; 12 | -------------------------------------------------------------------------------- /packages/intl-messageformat/tests/setup.js: -------------------------------------------------------------------------------- 1 | global.DOMParser = new (require('jsdom').JSDOM)().window.DOMParser 2 | -------------------------------------------------------------------------------- /packages/intl-messageformat/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "esnext", 5 | "outDir": "lib" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-messageformat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src"], 8 | "references": [ 9 | {"path": "../intl-pluralrules"}, 10 | {"path": "../intl-format-cache"}, 11 | {"path": "../intl-messageformat-parser"} 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/.gitignore: -------------------------------------------------------------------------------- 1 | src/en.ts 2 | src/locales.js 3 | src/units-constants.ts 4 | polyfill-locales.js 5 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/README.md: -------------------------------------------------------------------------------- 1 | # `intl-pluralrules` 2 | 3 | We've migrated the README to [here](../../website/docs/polyfills/intl-pluralrules.md). 4 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-pluralrules/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/intl-pluralrules", 3 | "version": "1.5.6", 4 | "description": "Polyfill for intl plural rules", 5 | "keywords": [ 6 | "polyfill", 7 | "i18n", 8 | "intl", 9 | "plural", 10 | "rules" 11 | ], 12 | "author": "Long Ho ", 13 | "homepage": "https://github.com/formatjs/formatjs", 14 | "license": "MIT", 15 | "main": "dist/index.js", 16 | "module": "lib/index.js", 17 | "types": "lib/intl-pluralrules.d.ts", 18 | "files": [ 19 | "dist-es6", 20 | "dist", 21 | "lib", 22 | "polyfill-locales.js", 23 | "polyfill.js", 24 | "src" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/formatjs/formatjs.git" 29 | }, 30 | "devDependencies": { 31 | "formatjs-extract-cldr-data": "^10.1.5" 32 | }, 33 | "dependencies": { 34 | "@formatjs/intl-utils": "^2.2.3" 35 | }, 36 | "scripts": { 37 | "build": "yarn run cldr && yarn run compile", 38 | "cldr": "ts-node scripts/cldr", 39 | "clean": "rimraf dist lib dist-es6 polyfill-locales.js *.tsbuildinfo", 40 | "compile": "tsc && tsc -p tsconfig.esm.json && api-extractor run --local && tsc -p tsconfig.es6.json && rollup -c rollup.config.js", 41 | "jest": "cross-env NODE_ICU_DATA=../../node_modules/full-icu cross-env NODE_ENV=test jest", 42 | "test262": "cross-env NODE_ICU_DATA=../../node_modules/full-icu ts-node tests/runner", 43 | "test": "yarn run jest && yarn run test262" 44 | }, 45 | "bugs": { 46 | "url": "https://github.com/formatjs/formatjs/issues" 47 | }, 48 | "gitHead": "a7842673d8ad205171ad7c8cb8bb2f318b427c0c" 49 | } 50 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/polyfill.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill') 2 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { uglify } from 'rollup-plugin-uglify'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | 4 | const resolveConfig = resolve({ 5 | mainFields: ['module', 'main'] 6 | }); 7 | const uglifyConfig = uglify(); 8 | export default [ 9 | { 10 | input: './lib/index.js', 11 | output: { 12 | sourcemap: true, 13 | file: 'dist/umd/intl-pluralrules.js', 14 | format: 'umd', 15 | exports: 'named', 16 | name: 'IntlPluralRules' 17 | }, 18 | plugins: [resolveConfig] 19 | }, 20 | { 21 | input: './lib/index.js', 22 | output: { 23 | sourcemap: true, 24 | file: 'dist/umd/intl-pluralrules.min.js', 25 | format: 'umd', 26 | exports: 'named', 27 | name: 'IntlPluralRules' 28 | }, 29 | plugins: [resolveConfig, uglifyConfig] 30 | }, 31 | { 32 | input: './lib/polyfill.js', 33 | output: { 34 | sourcemap: true, 35 | file: 'dist/umd/polyfill.js', 36 | format: 'umd' 37 | }, 38 | plugins: [resolveConfig] 39 | }, 40 | { 41 | input: './dist-es6/polyfill-locales.js', 42 | output: { 43 | sourcemap: true, 44 | file: 'dist/umd/polyfill-with-locales.js', 45 | format: 'umd', 46 | }, 47 | plugins: [resolveConfig] 48 | }, 49 | { 50 | input: './dist-es6/polyfill-locales.js', 51 | output: { 52 | sourcemap: true, 53 | file: 'dist/polyfill-with-locales-for-test262.min.js', 54 | format: 'umd', 55 | exports: 'named', 56 | name: 'IntlPluralRules' 57 | }, 58 | plugins: [resolveConfig] 59 | }, 60 | ]; -------------------------------------------------------------------------------- /packages/intl-pluralrules/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './core'; 2 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import {PluralRules} from './core'; 2 | 3 | if ( 4 | typeof Intl.PluralRules === 'undefined' || 5 | (!(Intl.PluralRules as any).polyfilled && 6 | new Intl.PluralRules('en', {minimumFractionDigits: 2} as any).select(1) === 7 | 'one') 8 | ) { 9 | Object.defineProperty(Intl, 'PluralRules', { 10 | value: PluralRules, 11 | writable: true, 12 | enumerable: false, 13 | configurable: true, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/tests/supported-locales-of.test.ts: -------------------------------------------------------------------------------- 1 | import '../src/polyfill'; 2 | import '../polyfill'; 3 | import '../dist/locale-data/zh'; 4 | 5 | describe('supportedLocalesOf', function () { 6 | function test() { 7 | expect(Intl.PluralRules.supportedLocalesOf(['zh', 'en-jj'])).toContain( 8 | 'zh' 9 | ); 10 | expect(Intl.PluralRules.supportedLocalesOf(['fr'])).toEqual([]); 11 | } 12 | 13 | if ((Intl.PluralRules as any).polyfilled) { 14 | it('should return correct locales that we only have data for', test); 15 | } else { 16 | it.skip('should return correct locales that we only have data for', test); 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "module": "esnext", 6 | "outDir": "dist-es6", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext", 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-pluralrules/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "es5", "esnext.intl", "es2017.intl", "es2018.intl"], 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "types": [ 8 | "babel__core", 9 | "babel__generator", 10 | "babel__template", 11 | "babel__traverse", 12 | "benchmark", 13 | "chai", 14 | "estree", 15 | "fs-extra", 16 | "istanbul-lib-coverage", 17 | "istanbul-lib-report", 18 | "istanbul-reports", 19 | // Don't include mocha here 20 | "jest", 21 | "jest-diff", 22 | "node", 23 | "resolve", 24 | "stack-utils", 25 | "yargs" 26 | ] 27 | }, 28 | "include": ["src"], 29 | "references": [{"path": "../formatjs-extract-cldr-data"}, {"path": "../intl-utils"}] 30 | } 31 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/.gitignore: -------------------------------------------------------------------------------- 1 | .nyc_output 2 | lib 3 | node_modules/ 4 | tests/browser.* 5 | src/locales.ts 6 | src/en.ts 7 | tests/polyfill-all.js 8 | dist-es6/ -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/README.md: -------------------------------------------------------------------------------- 1 | # Intl RelativeTimeFormat 2 | 3 | We've migrated the README to [here](../../website/docs/polyfills/intl-relativetimeformat.md). 4 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/intl-relativetimeformat", 3 | "version": "4.5.13", 4 | "description": "Formats JavaScript dates to relative time strings.", 5 | "keywords": [ 6 | "intl", 7 | "i18n", 8 | "relative", 9 | "time", 10 | "moment", 11 | "format", 12 | "date" 13 | ], 14 | "author": "Long Ho ", 15 | "bugs": { 16 | "url": "https://github.com/formatjs/formatjs/issues" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git@github.com:formatjs/formatjs.git" 21 | }, 22 | "devDependencies": { 23 | "@formatjs/intl-pluralrules": "^1.5.6", 24 | "formatjs-extract-cldr-data": "^10.1.5" 25 | }, 26 | "dependencies": { 27 | "@formatjs/intl-utils": "^2.2.3" 28 | }, 29 | "main": "dist/index.js", 30 | "module": "lib/index.js", 31 | "types": "lib/intl-relativetimeformat.d.ts", 32 | "scripts": { 33 | "build": "yarn run cldr && yarn run compile", 34 | "cldr": "ts-node scripts/cldr", 35 | "clean": "rimraf dist lib dist-es6 *.tsbuildinfo", 36 | "compile": "tsc && tsc -p tsconfig.esm.json && api-extractor run --local && tsc -p tsconfig.es6.json && rollup -c rollup.config.js", 37 | "jest": "cross-env NODE_ICU_DATA=../../node_modules/full-icu cross-env NODE_ENV=test jest", 38 | "test262": "cross-env NODE_ICU_DATA=../../node_modules/full-icu ts-node tests/runner", 39 | "test": "yarn run jest && yarn run test262" 40 | }, 41 | "files": [ 42 | "dist-es6", 43 | "dist", 44 | "lib", 45 | "polyfill-locales.js", 46 | "polyfill.js", 47 | "src" 48 | ], 49 | "homepage": "https://github.com/formatjs/formatjs", 50 | "license": "MIT", 51 | "gitHead": "a7842673d8ad205171ad7c8cb8bb2f318b427c0c" 52 | } 53 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/polyfill-locales.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill-locales') -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/polyfill.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill') -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/src/index.ts: -------------------------------------------------------------------------------- 1 | import IntlRelativeTimeFormat from './core'; 2 | export * from './core'; 3 | export * from './types'; 4 | export default IntlRelativeTimeFormat; 5 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/src/polyfill-locales.ts: -------------------------------------------------------------------------------- 1 | import './polyfill'; 2 | import './locales'; 3 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import RelativeTimeFormat from './core'; 2 | if (!('RelativeTimeFormat' in Intl)) { 3 | Object.defineProperty(Intl, 'RelativeTimeFormat', { 4 | value: RelativeTimeFormat, 5 | writable: true, 6 | enumerable: false, 7 | configurable: true, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/src/types.ts: -------------------------------------------------------------------------------- 1 | export type Unit = 2 | | 'second' 3 | | 'minute' 4 | | 'hour' 5 | | 'day' 6 | | 'week' 7 | | 'month' 8 | | 'quarter' 9 | | 'year'; 10 | 11 | export type Units = 12 | | 'seconds' 13 | | 'minutes' 14 | | 'hours' 15 | | 'days' 16 | | 'weeks' 17 | | 'months' 18 | | 'quarters' 19 | | 'years'; 20 | 21 | export type FormattableUnit = Unit | Units; 22 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import '@formatjs/intl-pluralrules/polyfill-locales'; 2 | import '../src/polyfill'; 3 | import '../polyfill'; 4 | import '../dist/locale-data/zh'; 5 | import '../dist/locale-data/en'; 6 | 7 | describe('Intl.RelativeTimeFormat', function () { 8 | const RelativeTimeFormat = (Intl as any).RelativeTimeFormat; 9 | it('should lookup zh-CN', function () { 10 | expect(new RelativeTimeFormat('zh-CN').format(-1, 'second')).toBe( 11 | '1秒钟前' 12 | ); 13 | }); 14 | it('should lookup zh-TW', function () { 15 | expect(new RelativeTimeFormat('zh-TW').format(-1, 'second')).toBe('1 秒前'); 16 | }); 17 | it('should resolve parent correctly', function () { 18 | expect(new RelativeTimeFormat('en-AI').format(-1, 'second')).toBe( 19 | '1 second ago' 20 | ); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/tests/supported-locales-of.test.ts: -------------------------------------------------------------------------------- 1 | import '@formatjs/intl-pluralrules/polyfill-locales'; 2 | import '../src/polyfill'; 3 | import '../polyfill'; 4 | import '../dist/locale-data/zh'; 5 | 6 | describe('supportedLocalesOf', function () { 7 | const RelativeTimeFormat = (Intl as any).RelativeTimeFormat; 8 | function test() { 9 | expect(RelativeTimeFormat.supportedLocalesOf(['zh', 'en-jj'])).toContain( 10 | 'zh' 11 | ); 12 | expect(RelativeTimeFormat.supportedLocalesOf('fr')).toEqual([]); 13 | } 14 | if (RelativeTimeFormat.polyfilled) { 15 | it('should return correct locales that we only have data for', test); 16 | } else { 17 | it.skip('should return correct locales that we only have data for', test); 18 | } 19 | }); 20 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "module": "esnext", 6 | "outDir": "dist-es6" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext" 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-relativetimeformat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "es5", "esnext.intl", "es2017.intl", "es2018.intl"], 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "downlevelIteration": true, 8 | "types": [ 9 | "babel__core", 10 | "babel__generator", 11 | "babel__template", 12 | "babel__traverse", 13 | "benchmark", 14 | "chai", 15 | "estree", 16 | "fs-extra", 17 | "istanbul-lib-coverage", 18 | "istanbul-lib-report", 19 | "istanbul-reports", 20 | // Don't include mocha here 21 | "jest", 22 | "jest-diff", 23 | "node", 24 | "resolve", 25 | "stack-utils", 26 | "yargs" 27 | ] 28 | }, 29 | "include": ["src"], 30 | "references": [ 31 | {"path": "../intl-pluralrules"}, 32 | {"path": "../formatjs-extract-cldr-data"}, 33 | {"path": "../intl-utils"} 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/.gitignore: -------------------------------------------------------------------------------- 1 | src/en.ts 2 | src/locales.ts 3 | src/units-constants.ts 4 | src/currency-digits.json 5 | src/ilnd-numbers.json -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/README.md: -------------------------------------------------------------------------------- 1 | # `intl-unified-numberformat` 2 | 3 | We've migrated the README to [here](../../website/docs/polyfills/intl-numberformat.md). 4 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/polyfill.js: -------------------------------------------------------------------------------- 1 | require('./dist/polyfill') -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/src/index.ts: -------------------------------------------------------------------------------- 1 | export {Unit} from './units-constants'; 2 | export * from './core'; 3 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/src/numbering-systems.json: -------------------------------------------------------------------------------- 1 | {"names":["adlm","ahom","arab","arabext","armn","armnlow","bali","beng","bhks","brah","cakm","cham","cyrl","deva","ethi","fullwide","geor","gong","gonm","grek","greklow","gujr","guru","hanidays","hanidec","hans","hansfin","hant","hantfin","hebr","hmng","hmnp","java","jpan","jpanfin","jpanyear","kali","khmr","knda","lana","lanatham","laoo","latn","lepc","limb","mathbold","mathdbl","mathmono","mathsanb","mathsans","mlym","modi","mong","mroo","mtei","mymr","mymrshan","mymrtlng","newa","nkoo","olck","orya","osma","rohg","roman","romanlow","saur","shrd","sind","sinh","sora","sund","takr","talu","taml","tamldec","telu","thai","tibt","tirh","vaii","wara","wcho"]} 2 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/src/polyfill.ts: -------------------------------------------------------------------------------- 1 | import {UnifiedNumberFormat, isUnitSupported} from './core'; 2 | 3 | if (!isUnitSupported('bit')) { 4 | Intl.NumberFormat = UnifiedNumberFormat as any; 5 | } 6 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/tests/value-tonumber.test.ts: -------------------------------------------------------------------------------- 1 | import '@formatjs/intl-pluralrules/polyfill-locales'; 2 | import {UnifiedNumberFormat} from '../src/core'; 3 | UnifiedNumberFormat.__addLocaleData(require('../dist/locale-data/en.json')); 4 | const toNumberResults = [ 5 | [undefined, NaN], 6 | [null, +0], 7 | [true, 1], 8 | [false, +0], 9 | ['42', 42], 10 | ['foo', NaN], 11 | ]; 12 | 13 | describe('value-tonumber', function () { 14 | const nf = new UnifiedNumberFormat(); 15 | for (const [val1, val2] of toNumberResults) { 16 | it(`${val1} === ${val2}`, function () { 17 | expect(nf.formatToParts(val1 as number)).toEqual( 18 | nf.formatToParts(val2 as number) 19 | ); 20 | }); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "module": "esnext", 6 | "outDir": "dist-es6", 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-unified-numberformat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["dom", "es5", "esnext.intl", "es2017.intl", "es2018.intl"], 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "types": [ 8 | "babel__core", 9 | "babel__generator", 10 | "babel__template", 11 | "babel__traverse", 12 | "benchmark", 13 | "chai", 14 | "estree", 15 | "fs-extra", 16 | "istanbul-lib-coverage", 17 | "istanbul-lib-report", 18 | "istanbul-reports", 19 | // Don't include mocha here 20 | "jest", 21 | "jest-diff", 22 | "node", 23 | "resolve", 24 | "stack-utils", 25 | "yargs" 26 | ] 27 | }, 28 | "include": ["src", "src/**/*.json"], 29 | "references": [ 30 | {"path": "../intl-pluralrules"}, 31 | {"path": "../formatjs-extract-cldr-data"}, 32 | {"path": "../intl-utils"}, 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /packages/intl-utils/.gitignore: -------------------------------------------------------------------------------- 1 | .nyc_output 2 | lib 3 | node_modules/ 4 | tests/browser.* 5 | src/aliases.ts 6 | src/parentLocales.ts -------------------------------------------------------------------------------- /packages/intl-utils/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/intl-utils/api-extractor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../api-extractor.json" 3 | } -------------------------------------------------------------------------------- /packages/intl-utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/intl-utils", 3 | "version": "2.2.3", 4 | "description": "Smartly determine best unit for relative time format", 5 | "keywords": [ 6 | "intl", 7 | "i18n", 8 | "relative", 9 | "moment", 10 | "format", 11 | "date" 12 | ], 13 | "author": "Long Ho using _replacement 11 | */ 12 | const localeAliases = Object.keys(languageAlias).reduce( 13 | (all: Record, locale) => { 14 | all[locale] = languageAlias[locale as 'zh-CN']._replacement; 15 | return all; 16 | }, 17 | {} 18 | ); 19 | 20 | const parentLocales = PARENT_LOCALES.supplemental.parentLocales.parentLocale; 21 | const parentLocaleMap = Object.keys(parentLocales).reduce( 22 | (all: Record, locale: string) => { 23 | if (parentLocales[locale as 'en-150'] !== 'root') { 24 | all[locale] = parentLocales[locale as 'en-150']; 25 | } 26 | return all; 27 | }, 28 | {} 29 | ); 30 | 31 | outputFileSync( 32 | resolve(__dirname, '../src/aliases.ts'), 33 | `/* @generated */ 34 | // prettier-ignore 35 | export default ${serialize(localeAliases)} 36 | ` 37 | ); 38 | 39 | outputFileSync( 40 | resolve(__dirname, '../src/parentLocales.ts'), 41 | `/* @generated */ 42 | // prettier-ignore 43 | export default ${serialize(parentLocaleMap)} 44 | ` 45 | ); 46 | -------------------------------------------------------------------------------- /packages/intl-utils/src/displaynames-types.ts: -------------------------------------------------------------------------------- 1 | import {LocaleData} from './types'; 2 | 3 | type LanguageTag = string; 4 | type RegionCode = string; 5 | type ScriptCode = string; 6 | type CurrencyCode = string; 7 | 8 | export interface DisplayNamesData { 9 | /** 10 | * Note that for style fields, `short` and `narrow` might not exist. 11 | * At runtime, the fallback order will be narrow -> short -> long. 12 | */ 13 | types: { 14 | /** 15 | * Maps language subtag like `zh-CN` to their display names. 16 | */ 17 | language: { 18 | narrow: Record; 19 | short: Record; 20 | long: Record; 21 | }; 22 | region: { 23 | narrow: Record; 24 | short: Record; 25 | long: Record; 26 | }; 27 | script: { 28 | narrow: Record; 29 | short: Record; 30 | long: Record; 31 | }; 32 | currency: { 33 | narrow: Record; 34 | short: Record; 35 | long: Record; 36 | }; 37 | }; 38 | /** 39 | * Not in spec, but we need this to display both language and region in display name. 40 | * e.g. zh-Hans-SG + "{0}({1})" -> 简体中文(新加坡) 41 | * Here {0} is replaced by language display name and {1} is replaced by region display name. 42 | */ 43 | patterns: { 44 | locale: string; 45 | }; 46 | } 47 | 48 | export type DisplayNamesLocaleData = LocaleData; 49 | -------------------------------------------------------------------------------- /packages/intl-utils/src/get-canonical-locales.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * IE11-safe version of getCanonicalLocales since it's ES2016 3 | * @param locales locales 4 | */ 5 | export function getCanonicalLocales(locales?: string | string[]): string[] { 6 | // IE11 7 | const {getCanonicalLocales} = Intl as any; 8 | if (typeof getCanonicalLocales === 'function') { 9 | return getCanonicalLocales(locales) as string[]; 10 | } 11 | // NOTE: we must NOT call `supportedLocalesOf` of a formatjs polyfill, or their implementation 12 | // will even eventually call this method recursively. Here we use `Intl.DateTimeFormat` since it 13 | // is not polyfilled by `@formatjs`. 14 | return Intl.DateTimeFormat.supportedLocalesOf(locales || ''); 15 | } 16 | -------------------------------------------------------------------------------- /packages/intl-utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export {selectUnit} from './diff'; 2 | export { 3 | defaultNumberOption, 4 | getAliasesByLang, 5 | getInternalSlot, 6 | getMultiInternalSlots, 7 | getNumberOption, 8 | getOption, 9 | getParentLocalesByLang, 10 | isLiteralPart, 11 | LiteralPart, 12 | partitionPattern, 13 | setInternalSlot, 14 | setMultiInternalSlots, 15 | setNumberFormatDigitOptions, 16 | toObject, 17 | objectIs, 18 | isWellFormedCurrencyCode, 19 | toString, 20 | } from './polyfill-utils'; 21 | export { 22 | createResolveLocale, 23 | getLocaleHierarchy, 24 | supportedLocales, 25 | unpackData, 26 | isMissingLocaleDataError, 27 | } from './resolve-locale'; 28 | export * from './units'; 29 | export * from './relative-time-types'; 30 | export * from './unified-numberformat-types'; 31 | export * from './list-types'; 32 | export * from './plural-rules-types'; 33 | export * from './number-types'; 34 | export * from './displaynames-types'; 35 | export {getCanonicalLocales} from './get-canonical-locales'; 36 | export {invariant} from './invariant'; 37 | -------------------------------------------------------------------------------- /packages/intl-utils/src/invariant.ts: -------------------------------------------------------------------------------- 1 | export function invariant( 2 | condition: boolean, 3 | message: string, 4 | Err: any = Error 5 | ) { 6 | if (!condition) { 7 | throw new Err(message); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/intl-utils/src/list-types.ts: -------------------------------------------------------------------------------- 1 | import {LocaleData} from './types'; 2 | 3 | export type ListPatternLocaleData = LocaleData; 4 | 5 | export interface ListPatternFieldsData { 6 | conjunction?: ListPatternData; 7 | disjunction?: ListPatternData; 8 | unit?: ListPatternData; 9 | } 10 | 11 | export interface ListPattern { 12 | start: string; 13 | middle: string; 14 | end: string; 15 | pair: string; 16 | } 17 | 18 | export interface ListPatternData { 19 | long: ListPattern; 20 | short?: ListPattern; 21 | narrow?: ListPattern; 22 | } 23 | -------------------------------------------------------------------------------- /packages/intl-utils/src/plural-rules-types.ts: -------------------------------------------------------------------------------- 1 | import {LocaleData} from './types'; 2 | export type LDMLPluralRule = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'; 3 | export interface PluralRulesData { 4 | categories: { 5 | cardinal: string[]; 6 | ordinal: string[]; 7 | }; 8 | fn: (val: number | string, ord?: boolean) => LDMLPluralRule; 9 | } 10 | 11 | export type PluralRulesLocaleData = LocaleData; 12 | -------------------------------------------------------------------------------- /packages/intl-utils/src/relative-time-types.ts: -------------------------------------------------------------------------------- 1 | import {LocaleData} from './types'; 2 | import {LDMLPluralRule} from './plural-rules-types'; 3 | 4 | export interface FieldData { 5 | '0'?: string; 6 | '1'?: string; 7 | '-1'?: string; 8 | '2'?: string; 9 | '-2'?: string; 10 | '3'?: string; 11 | '-3'?: string; 12 | future: RelativeTimeData; 13 | past: RelativeTimeData; 14 | } 15 | 16 | type RelativeTimeData = {[u in LDMLPluralRule]?: string}; 17 | 18 | export type UnpackedLocaleFieldsData = { 19 | [f in RelativeTimeField]?: FieldData; 20 | } & {nu: Array}; 21 | 22 | export type LocaleFieldsData = { 23 | [f in RelativeTimeField]?: FieldData; 24 | } & {nu?: Array}; 25 | 26 | export type RelativeTimeField = 27 | | 'second' 28 | | 'second-short' 29 | | 'second-narrow' 30 | | 'minute' 31 | | 'minute-short' 32 | | 'minute-narrow' 33 | | 'hour' 34 | | 'hour-short' 35 | | 'hour-narrow' 36 | | 'day' 37 | | 'day-short' 38 | | 'day-narrow' 39 | | 'week' 40 | | 'week-short' 41 | | 'week-narrow' 42 | | 'month' 43 | | 'month-short' 44 | | 'month-narrow' 45 | | 'quarter' 46 | | 'quarter-short' 47 | | 'quarter-narrow' 48 | | 'year' 49 | | 'year-short' 50 | | 'year-narrow'; 51 | 52 | export type RelativeTimeLocaleData = LocaleData; 53 | -------------------------------------------------------------------------------- /packages/intl-utils/src/types.ts: -------------------------------------------------------------------------------- 1 | export type Locale = string; 2 | export interface LocaleData { 3 | data: Record; 4 | aliases: Record; 5 | availableLocales: string[]; 6 | parentLocales: Record; 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-utils/src/unified-numberformat-types.ts: -------------------------------------------------------------------------------- 1 | import {LocaleData} from './types'; 2 | import {NumberInternalSlots} from './number-types'; 3 | 4 | export type UnifiedNumberFormatLocaleData = LocaleData; 5 | 6 | export type UnifiedNumberFormatOptionsLocaleMatcher = 'lookup' | 'best fit'; 7 | export type UnifiedNumberFormatOptionsStyle = 8 | | 'decimal' 9 | | 'percent' 10 | | 'currency' 11 | | 'unit'; 12 | export type UnifiedNumberFormatOptionsCompactDisplay = 'short' | 'long'; 13 | export type UnifiedNumberFormatOptionsCurrencyDisplay = 14 | | 'symbol' 15 | | 'code' 16 | | 'name' 17 | | 'narrowSymbol'; 18 | export type UnifiedNumberFormatOptionsCurrencySign = 'standard' | 'accounting'; 19 | export type UnifiedNumberFormatOptionsNotation = 20 | | 'standard' 21 | | 'scientific' 22 | | 'engineering' 23 | | 'compact'; 24 | export type UnifiedNumberFormatOptionsSignDisplay = 25 | | 'auto' 26 | | 'always' 27 | | 'never' 28 | | 'exceptZero'; 29 | export type UnifiedNumberFormatOptionsUnitDisplay = 'long' | 'short' | 'narrow'; 30 | -------------------------------------------------------------------------------- /packages/intl-utils/src/units.ts: -------------------------------------------------------------------------------- 1 | // https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_diff_out.html#sec-issanctionedsimpleunitidentifier 2 | export const SANCTIONED_UNITS = [ 3 | 'angle-degree', 4 | 'area-acre', 5 | 'area-hectare', 6 | 'concentr-percent', 7 | 'digital-bit', 8 | 'digital-byte', 9 | 'digital-gigabit', 10 | 'digital-gigabyte', 11 | 'digital-kilobit', 12 | 'digital-kilobyte', 13 | 'digital-megabit', 14 | 'digital-megabyte', 15 | 'digital-petabyte', 16 | 'digital-terabit', 17 | 'digital-terabyte', 18 | 'duration-day', 19 | 'duration-hour', 20 | 'duration-millisecond', 21 | 'duration-minute', 22 | 'duration-month', 23 | 'duration-second', 24 | 'duration-week', 25 | 'duration-year', 26 | 'length-centimeter', 27 | 'length-foot', 28 | 'length-inch', 29 | 'length-kilometer', 30 | 'length-meter', 31 | 'length-mile-scandinavian', 32 | 'length-mile', 33 | 'length-millimeter', 34 | 'length-yard', 35 | 'mass-gram', 36 | 'mass-kilogram', 37 | 'mass-ounce', 38 | 'mass-pound', 39 | 'mass-stone', 40 | 'temperature-celsius', 41 | 'temperature-fahrenheit', 42 | 'volume-fluid-ounce', 43 | 'volume-gallon', 44 | 'volume-liter', 45 | 'volume-milliliter', 46 | ]; 47 | 48 | // In CLDR, the unit name always follows the form `namespace-unit` pattern. 49 | // For example: `digital-bit` instead of `bit`. This function removes the namespace prefix. 50 | export function removeUnitNamespace(unit: string) { 51 | return unit.replace(/^(.*?)-/, ''); 52 | } 53 | -------------------------------------------------------------------------------- /packages/intl-utils/tests/polyfill-utils.ts: -------------------------------------------------------------------------------- 1 | import {partitionPattern} from '../src/polyfill-utils'; 2 | describe('polyfill-utils', function () { 3 | it('should partition pattern correctly', function () { 4 | expect(partitionPattern('AA{0}BB')).to.deep.equal([ 5 | { 6 | type: 'literal', 7 | value: 'AA', 8 | }, 9 | { 10 | type: '0', 11 | value: undefined, 12 | }, 13 | { 14 | type: 'literal', 15 | value: 'BB', 16 | }, 17 | ]); 18 | expect(partitionPattern('{0} BB')).to.deep.equal([ 19 | { 20 | type: '0', 21 | value: undefined, 22 | }, 23 | { 24 | type: 'literal', 25 | value: ' BB', 26 | }, 27 | ]); 28 | expect(partitionPattern('AA {0}')).to.deep.equal([ 29 | { 30 | type: 'literal', 31 | value: 'AA ', 32 | }, 33 | { 34 | type: '0', 35 | value: undefined, 36 | }, 37 | ]); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/intl-utils/tsconfig.es6.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "module": "esnext", 6 | "outDir": "dist-es6", 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /packages/intl-utils/tsconfig.esm.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "lib", 5 | "module": "esnext", 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /packages/intl-utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/macro/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/macro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/macro", 3 | "version": "0.2.7", 4 | "description": "formatjs-related compiler macros", 5 | "keywords": [ 6 | "intl", 7 | "i18n", 8 | "internationalization", 9 | "locale", 10 | "localization", 11 | "globalization", 12 | "react", 13 | "react-intl", 14 | "reactjs", 15 | "format", 16 | "formatjs", 17 | "formatting", 18 | "translate", 19 | "translation", 20 | "macro" 21 | ], 22 | "main": "dist/index.js", 23 | "types": "dist/index.d.ts", 24 | "author": "Long Ho ", 25 | "homepage": "https://github.com/formatjs/formatjs", 26 | "license": "MIT", 27 | "repository": { 28 | "type": "git", 29 | "url": "git+ssh://git@github.com/formatjs/formatjs.git" 30 | }, 31 | "scripts": { 32 | "clean": "rimraf lib *.tsbuildinfo", 33 | "build": "tsc" 34 | }, 35 | "files": [ 36 | "dist", 37 | "src" 38 | ], 39 | "bugs": { 40 | "url": "https://github.com/formatjs/formatjs/issues" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/macro/src/index.ts: -------------------------------------------------------------------------------- 1 | export function _(msg: T): T { 2 | return msg; 3 | } 4 | 5 | export function defineMessages>(msgs: U): U { 6 | return msgs; 7 | } 8 | -------------------------------------------------------------------------------- /packages/macro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es2019", 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "noUnusedLocals": true, 8 | "sourceMap": true, 9 | "types": [ 10 | "babel__core", 11 | "babel__generator", 12 | "babel__template", 13 | "babel__traverse", 14 | "benchmark", 15 | "chai", 16 | "estree", 17 | "fs-extra", 18 | "istanbul-lib-coverage", 19 | "istanbul-lib-report", 20 | "istanbul-reports", 21 | // Don't include mocha here 22 | "jest", 23 | "node", 24 | "resolve", 25 | "stack-utils", 26 | "yargs" 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/ts-transformer/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | test/*.js 40 | test/*.d.ts -------------------------------------------------------------------------------- /packages/ts-transformer/LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FormatJS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /packages/ts-transformer/README.md: -------------------------------------------------------------------------------- 1 | # @formatjs/ts-transformer 2 | 3 | We've migrated the README to [here](../../website/docs/tooling/ts-transformer.md). 4 | -------------------------------------------------------------------------------- /packages/ts-transformer/compile.ts: -------------------------------------------------------------------------------- 1 | import * as ts from 'typescript' 2 | import {Project} from 'ts-morph' 3 | import { transform as intlTransformer } from "./src"; 4 | 5 | declare module "fs-extra" { 6 | export function outputJsonSync(file: string, data: any, opts?: {}): void; 7 | } 8 | const CJS_CONFIG: ts.CompilerOptions = { 9 | experimentalDecorators: true, 10 | jsx: ts.JsxEmit.React, 11 | module: ts.ModuleKind.CommonJS, 12 | moduleResolution: ts.ModuleResolutionKind.NodeJs, 13 | noEmitOnError: false, 14 | noUnusedLocals: true, 15 | noUnusedParameters: true, 16 | stripInternal: true, 17 | declaration: true, 18 | baseUrl: __dirname, 19 | target: ts.ScriptTarget.ES2015 20 | }; 21 | 22 | export default function compile( 23 | input: string, 24 | compilerOptions: ts.CompilerOptions = CJS_CONFIG 25 | ) { 26 | const project = new Project({ 27 | compilerOptions 28 | }) 29 | project.addExistingSourceFiles(input) 30 | 31 | const msgs = {}; 32 | 33 | project.emit({ 34 | customTransformers: { 35 | before: [ 36 | intlTransformer({ 37 | overrideIdFn: "[hash:base64:10]", 38 | program: project.getProgram().compilerObject 39 | }) 40 | ] 41 | }}); 42 | const diagnostics = project.getPreEmitDiagnostics(); 43 | 44 | console.log(project.formatDiagnosticsWithColorAndContext(diagnostics)); 45 | return msgs; 46 | } 47 | -------------------------------------------------------------------------------- /packages/ts-transformer/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | globals: { 5 | 'ts-jest': { 6 | tsConfig: 'tsconfig.json' 7 | } 8 | } 9 | }; -------------------------------------------------------------------------------- /packages/ts-transformer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@formatjs/ts-transformer", 3 | "version": "1.1.5", 4 | "description": "TS Compiler transformer for formatjs", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "test": "rm -rf test/fixture/*.js && cross-env NODE_ENV=test jest --maxWorkers=100%", 8 | "build": "tsc" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+ssh://git@github.com/formatjs/formatjs.git" 13 | }, 14 | "keywords": [ 15 | "i18n", 16 | "internationalization", 17 | "typescript", 18 | "transform", 19 | "transformer", 20 | "react-intl" 21 | ], 22 | "dependencies": { 23 | "@types/loader-utils": "^1.1.3", 24 | "loader-utils": "^2.0.0", 25 | "typescript": "3.7.2" 26 | }, 27 | "author": "Long Ho ", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/formatjs/formatjs/issues" 31 | }, 32 | "homepage": "https://github.com/formatjs/formatjs#readme" 33 | } 34 | -------------------------------------------------------------------------------- /packages/ts-transformer/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './transform'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /packages/ts-transformer/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface MessageDescriptor { 2 | id?: string; 3 | description?: string; 4 | defaultMessage?: string; 5 | file?: string; 6 | start?: number; 7 | end?: number; 8 | } 9 | 10 | export interface Messages { 11 | [key: string]: MessageDescriptor; 12 | } 13 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/FormattedMessage.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return ( 7 | 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/additionalComponentNames.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | function CustomMessage() {} 4 | 5 | export default class Foo extends Component { 6 | render() { 7 | return ( 8 | 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/defineMessages.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const msgs = defineMessages({ 5 | header: { 6 | id: 'foo.bar.baz', 7 | defaultMessage: 'Hello World!', 8 | description: 'The default message', 9 | }, 10 | content: { 11 | id: 'foo.bar.biff', 12 | defaultMessage: 'Hello Nurse!', 13 | description: 'Another message', 14 | }, 15 | kittens: { 16 | id: 'app.home.kittens', 17 | description: 'Counts kittens', 18 | defaultMessage: '{count, plural, =0 {😭} one {# kitten} other {# kittens}}', 19 | }, 20 | trailingWhitespace: { 21 | id: 'trailing.ws', 22 | description: 'Whitespace', 23 | defaultMessage: ' Some whitespace ', 24 | }, 25 | escaped: { 26 | id: 'escaped.apostrophe', 27 | description: 'Escaped apostrophe', 28 | defaultMessage: "A quoted value ''{value}'", 29 | }, 30 | quoted: { 31 | id: 'escaped.apostrophe', 32 | description: 'Escaped apostrophe', 33 | defaultMessage: "What's going on", 34 | }, 35 | newline: { 36 | id: 'newline', 37 | description: 'this is \ 38 | a \ 39 | description', 40 | defaultMessage: 'this is \ 41 | a message', 42 | }, 43 | }); 44 | 45 | export default class Foo extends Component { 46 | render() { 47 | return ( 48 |
49 |

50 | 51 |

52 |

53 | 54 |

55 |

56 | 57 |

58 |
59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/descriptionsAsObjects.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return ( 7 | 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/extractFromFormatMessage.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {injectIntl, FormattedMessage} from 'react-intl'; 3 | 4 | const objectPointer = { 5 | id: 'foo.bar.invalid', 6 | defaultMessage: 'This cannot be extracted', 7 | description: 'the plugin only supports inline objects', 8 | }; 9 | 10 | class Foo extends Component { 11 | render() { 12 | const {intl} = this.props; 13 | const msgs = { 14 | baz: this.props.intl.formatMessage({ 15 | id: 'foo.bar.baz', 16 | defaultMessage: 'Hello World!', 17 | description: 'The default message', 18 | }), 19 | biff: intl.formatMessage({ 20 | id: 'foo.bar.biff', 21 | defaultMessage: 'Hello Nurse!', 22 | description: 'Another message', 23 | }), 24 | invalid: this.props.intl.formatMessage(objectPointer), 25 | }; 26 | 27 | return ( 28 |
29 |

{msgs.header}

30 |

{msgs.content}

31 | 32 | 33 | 34 |
35 | ); 36 | } 37 | } 38 | 39 | export default injectIntl(Foo); 40 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/extractSourceLocation.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | 4 | export default class Foo extends Component { 5 | render() { 6 | return ; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/formatMessageCall.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {injectIntl, FormattedMessage} from 'react-intl'; 3 | 4 | const objectPointer = { 5 | id: 'foo.bar.invalid', 6 | defaultMessage: 'This cannot be extracted', 7 | description: 'the plugin only supports inline objects', 8 | }; 9 | 10 | class Foo extends Component { 11 | render() { 12 | const msgs = { 13 | baz: this.props.intl.formatMessage({ 14 | id: 'foo.bar.baz', 15 | defaultMessage: 'Hello World!', 16 | description: 'The default message', 17 | }), 18 | biff: this.props.intl.formatMessage({ 19 | id: 'foo.bar.biff', 20 | defaultMessage: 'Hello Nurse!', 21 | description: 'Another message', 22 | }), 23 | invalid: this.props.intl.formatMessage(objectPointer), 24 | }; 25 | 26 | return ( 27 |
28 |

{msgs.header}

29 |

{msgs.content}

30 | 31 | 32 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | export default injectIntl(Foo); 39 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/inline.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-intl'; 3 | import {_} from '@formatjs/macro'; 4 | 5 | export default class Foo extends Component { 6 | render() { 7 | return ( 8 |
9 | 14 | {_({ 15 | id: 'header', 16 | defaultMessage: 'Hello World!', 17 | description: 'The default message', 18 | })} 19 | {_({ 20 | id: 'header2', 21 | defaultMessage: 'Hello World!', 22 | description: 'The default message', 23 | })} 24 |
25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/moduleSourceName.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {FormattedMessage} from 'react-i18n'; 3 | import {defineMessages} from 'react-intl'; 4 | 5 | // These should be ignored because the `moduleSourceName` is configured to be: 6 | // `react-i18n`. 7 | const msgs = defineMessages({ 8 | header: { 9 | id: 'header', 10 | defaultMessage: 'Hello World!', 11 | description: 'The default message', 12 | }, 13 | content: { 14 | id: 'content', 15 | defaultMessage: 'Hello Nurse!', 16 | description: 'Another message', 17 | }, 18 | }); 19 | 20 | export default class Foo extends Component { 21 | render() { 22 | return ( 23 |
24 | 29 | {msgs} 30 |
31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/noImport.tsx: -------------------------------------------------------------------------------- 1 | export function foo () { 2 | props.intl.formatMessage({ 3 | defaultMessage: 'props {intl}', 4 | description: 'bar' 5 | }, {bar: 'bar'}) 6 | this.props.intl.formatMessage({ 7 | defaultMessage: 'this props {intl}', 8 | description: 'bar' 9 | }, {bar: 'bar'}) 10 | return intl.formatMessage({ 11 | defaultMessage: 'foo {bar}', 12 | description: 'bar' 13 | }, {bar: 'bar'}) 14 | } -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/overrideIdFn.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import { 3 | defineMessages, 4 | FormattedMessage, 5 | } from 'react-intl'; 6 | 7 | const msgs = defineMessages({ 8 | header: { 9 | id: 'foo.bar.baz', 10 | defaultMessage: 'Hello World!', 11 | description: 'The default message', 12 | }, 13 | content: { 14 | id: 'foo.bar.biff', 15 | defaultMessage: 'Hello Nurse!', 16 | description: { 17 | text: 'Something for the translator.', 18 | metadata: 'Additional metadata content.', 19 | }, 20 | }, 21 | }); 22 | 23 | export default class Foo extends Component { 24 | render() { 25 | this.props.intl.formatMessage({ 26 | defaultMessage: 'no-id', 27 | description: 'no-id' 28 | }) 29 | return ( 30 |
31 |

32 | 33 |

34 |

35 | 36 |

37 | 45 |
46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/removeDefaultMessage.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const messages = defineMessages({ 5 | foo: { 6 | id: 'greeting-user', 7 | description: 'Greeting the user', 8 | defaultMessage: 'Hello, {name}', 9 | }, 10 | }); 11 | 12 | export default class Foo extends Component { 13 | render() { 14 | return ( 15 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/ts-transformer/tests/fixtures/removeDescription.tsx: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {defineMessages, FormattedMessage} from 'react-intl'; 3 | 4 | const messages = defineMessages({ 5 | foo: { 6 | id: 'greeting-user', 7 | description: 'Greeting the user', 8 | defaultMessage: 'Hello, {name}', 9 | }, 10 | }); 11 | 12 | export default class Foo extends Component { 13 | render() { 14 | return ( 15 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/ts-transformer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "target": "es6", 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "noUnusedLocals": true, 8 | "sourceMap": true, 9 | "types": [ 10 | "eslint", 11 | "estree", 12 | "estree-jsx", 13 | "babel__core", 14 | "babel__generator", 15 | "babel__template", 16 | "babel__traverse", 17 | "benchmark", 18 | "chai", 19 | "estree", 20 | "fs-extra", 21 | "istanbul-lib-coverage", 22 | "istanbul-lib-report", 23 | "istanbul-reports", 24 | // Don't include mocha here 25 | "jest", 26 | "node", 27 | "resolve", 28 | "stack-utils", 29 | "yargs" 30 | ], 31 | }, 32 | "include": ["src"] 33 | } 34 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve'; 2 | import typescript from 'rollup-plugin-typescript2'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | import replace from 'rollup-plugin-replace'; 5 | 6 | const resolveConfig = resolve({ 7 | customResolveOptions: { 8 | '@formatjs/intl-pluralrules': './packages/intl-pluralrules', 9 | '@formatjs/intl-relativetimeformat': './packages/intl-relativetimeformat', 10 | '@formatjs/intl-utils': './packages/intl-utils', 11 | 'intl-messageformat': './packages/intl-messageformat', 12 | }, 13 | }); 14 | 15 | export default [ 16 | { 17 | input: './tests/index.ts', 18 | output: { 19 | sourcemap: true, 20 | file: 'tests/browser.js', 21 | format: 'umd', 22 | }, 23 | plugins: [ 24 | replace({ 25 | 'process.env.NODE_ENV': JSON.stringify('test'), 26 | 'process.version': JSON.stringify(''), 27 | }), 28 | resolveConfig, 29 | typescript({ 30 | // This is meant to be import and used in sub-packages, where a tsconfig.esm.json 31 | // is assumed to exist. 32 | tsconfig: './tsconfig.esm.json', 33 | tsconfigDefaults: { 34 | compilerOptions: { 35 | declaration: false, 36 | declarationMap: false, 37 | }, 38 | }, 39 | }), 40 | commonjs(), 41 | ], 42 | }, 43 | ]; 44 | -------------------------------------------------------------------------------- /tests/ensure_ts_project_reference_in_sync.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Ensure that project references in tsconfig.json of packages is in sync with Yarn workspace dependencies. 3 | */ 4 | 5 | import * as ts from 'typescript'; 6 | import path from 'path'; 7 | import {execSync} from 'child_process'; 8 | 9 | const REPO_ROOT = path.resolve(__dirname, '..'); 10 | const workspaceInfo = JSON.parse( 11 | execSync('yarn -s workspaces info').toString() 12 | ); 13 | 14 | for (const workspaceName of Object.keys(workspaceInfo)) { 15 | const {location, workspaceDependencies} = workspaceInfo[workspaceName]; 16 | const packageLocation = path.resolve(REPO_ROOT, location); 17 | const tsConfig = path.resolve(packageLocation, 'tsconfig.json'); 18 | 19 | test(`${workspaceName}: tsconfig.json project reference is in sync with \`yarn workspaces info\``, () => { 20 | const tsconfigData = ts.readConfigFile(tsConfig, ts.sys.readFile).config; 21 | expect(tsconfigData).toBeDefined(); 22 | 23 | if (workspaceDependencies.length === 0) { 24 | expect(tsconfigData.references || []).toEqual([]); 25 | } else { 26 | const expectedReferences = workspaceDependencies.map( 27 | (depWorkspaceName: string) => { 28 | const depLocation = workspaceInfo[depWorkspaceName].location; 29 | const depFolderName = path.basename(depLocation); 30 | return {path: `../${depFolderName}`}; 31 | } 32 | ); 33 | expect(tsconfigData.references).toHaveLength(expectedReferences.length); 34 | expect(tsconfigData.references).toEqual( 35 | expect.arrayContaining(expectedReferences) 36 | ); 37 | } 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /tests/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; 5 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2019", 5 | "strict": true, 6 | "allowSyntheticDefaultImports": true, 7 | "esModuleInterop": true, 8 | "types": ["jest"], 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "target": "es5", 6 | "lib": ["es6", "dom", "es2018.intl"], 7 | "declaration": true, 8 | "strict": true, 9 | "resolveJsonModule": true, 10 | "noUnusedLocals": true, 11 | "noUnusedParameters": true, 12 | "preserveConstEnums": true, 13 | "allowSyntheticDefaultImports": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "declarationMap": true, 16 | "sourceMap": true, 17 | "composite": true, 18 | "types": [ 19 | "babel__core", 20 | "babel__generator", 21 | "babel__template", 22 | "babel__traverse", 23 | "benchmark", 24 | "chai", 25 | "estree", 26 | "fs-extra", 27 | "istanbul-lib-coverage", 28 | "istanbul-lib-report", 29 | "istanbul-reports", 30 | // Don't include jest here 31 | "mocha", 32 | "node", 33 | "resolve", 34 | "stack-utils", 35 | "yargs" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | .docusaurus 2 | build 3 | .now -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /website/docs/libraries.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: libraries 3 | title: Libraries 4 | --- 5 | 6 | FormatJS also provides 2 high-level formatting libraries: 7 | 8 | - [Intl.MessageFormat](./intl-messageformat.md) 9 | - [`react-intl`](./react-intl.md) 10 | -------------------------------------------------------------------------------- /website/docs/polyfills.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: polyfills 3 | title: Polyfills 4 | --- 5 | 6 | One of our goals is to provide developers with access to newest ECMA-402 Intl APIs. Therefore, FormatJS suite also provide multiple high quality polyfills that are fully tested using the [Official ECMAScript Conformance Test Suite](https://github.com/tc39/test262). 7 | 8 | Our current list of polyfills includes: 9 | 10 | - [Intl.PluralRules](polyfills/intl-pluralrules.md) 11 | - [Intl.RelativeTimeFormat](polyfills/intl-relativetimeformat.md) 12 | - [Intl.ListFormat](polyfills/intl-listformat.md) 13 | - [Intl.DisplayNames](polyfills/intl-displaynames.md) 14 | - [Intl.NumberFormat](polyfills/intl-numberformat.md) (ES2020) 15 | -------------------------------------------------------------------------------- /website/docs/polyfills/intl-displaynames.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: intl-displaynames 3 | title: Intl.DisplayNames 4 | --- 5 | 6 | A ponyfill/polyfill for [`Intl.DisplayNames`](https://tc39.es/proposal-intl-displaynames). 7 | 8 | ## Installation 9 | 10 | ``` 11 | npm install @formatjs/intl-displaynames 12 | ``` 13 | 14 | # Features 15 | 16 | Everything in . 17 | 18 | # Usage 19 | 20 | To use the ponyfill, import it along with its data: 21 | 22 | ```ts 23 | import {DisplayNames} from '@formatjs/intl-displaynames'; 24 | DisplayNames.__addLocaleData( 25 | require('@formatjs/intl-displaynames/dist/locale-data/en.json') // locale-data for en 26 | ); 27 | DisplayNames.__addLocaleData( 28 | require('@formatjs/intl-displaynames/dist/locale-data/zh.json') // locale-data for zh 29 | ); 30 | 31 | new DisplayNames('zh', {type: 'currency'}).of('USD'); //=> "美元" 32 | ``` 33 | 34 | To use this as a polyfill, override `Intl.DisplayNames` as below: 35 | 36 | ```javascript 37 | import '@formatjs/intl-displaynames/polyfill'; 38 | import '@formatjs/intl-displaynames/dist/locale-data/en'; // locale-data for en 39 | import '@formatjs/intl-displaynames/dist/locale-data/zh'; // locale-data for zh 40 | 41 | new Intl.DisplayNames('en').of('zh-Hans'); //=> "Simplified Chinese" 42 | new Intl.DisplayNames('zh', {type: 'currency'}).of('USD'); //=> "美元" 43 | ``` 44 | -------------------------------------------------------------------------------- /website/docs/polyfills/intl-listformat.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: intl-listformat 3 | title: Intl.ListtFormat 4 | --- 5 | 6 | A spec-compliant polyfill/ponyfill for Intl.ListFormat fully tested by the [official ECMAScript Conformance test suite](https://github.com/tc39/test262) 7 | 8 | [![npm Version][npm-badge]][npm] 9 | ![size](https://badgen.net/bundlephobia/minzip/@formatjs/intl-listformat) 10 | 11 | ## Installation 12 | 13 | ``` 14 | npm install @formatjs/intl-listformat 15 | ``` 16 | 17 | ## Usage 18 | 19 | To use the polyfill, just import it to make sure that a fully functional Intl.ListFormat is available in your environment: 20 | 21 | ``` 22 | import '@formatjs/intl-listformat/polyfill' 23 | ``` 24 | 25 | If Intl.ListFormat already exists, the polyfill will not be loaded. 26 | 27 | To use this as a ponyfill: 28 | 29 | ``` 30 | import IntlListFormat from '@formatjs/intl-listformat' 31 | ``` 32 | 33 | By default, this library comes with `en` data. To load additional locale, you can include them on demand: 34 | 35 | ```js 36 | import '@formatjs/intl-listformat/polyfill'; 37 | import '@formatjs/intl-listformat/dist/locale-data/de'; // Add locale data for de 38 | ``` 39 | 40 | If you want to polyfill all locales (e.g for Node): 41 | 42 | ``` 43 | import '@formatjs/intl-listformat/polyfill-locales' 44 | ``` 45 | 46 | ## Tests 47 | 48 | This library is fully [test262](https://github.com/tc39/test262/tree/master/test/intl402/ListFormat)-compliant. 49 | 50 | [npm]: https://www.npmjs.org/package/@formatjs/intl-listformat 51 | [npm-badge]: https://img.shields.io/npm/v/@formatjs/intl-listformat.svg?style=flat-square 52 | -------------------------------------------------------------------------------- /website/docs/polyfills/intl-pluralrules.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: intl-pluralrules 3 | title: Intl.PluralRules 4 | --- 5 | 6 | A spec-compliant polyfill/ponyfill for [`Intl.PluralRules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules) fully tested by the [official ECMAScript Conformance test suite](https://github.com/tc39/test262) 7 | 8 | [![npm Version][npm-badge]][npm] 9 | ![size](https://badgen.net/bundlephobia/minzip/@formatjs/intl-pluralrules) 10 | 11 | ## Installation 12 | 13 | ``` 14 | npm install @formatjs/intl-pluralrules 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```tsx 20 | import '@formatjs/intl-pluralrules/polyfill'; 21 | import '@formatjs/intl-pluralrules/dist/locale-data/en'; // locale-data for en 22 | ``` 23 | 24 | TO polyfill w/ ALL locales: 25 | 26 | ```tsx 27 | import '@formatjs/intl-pluralrules/polyfill-locales'; 28 | ``` 29 | 30 | [npm]: https://www.npmjs.org/package/@formatjs/intl-pluralrules 31 | [npm-badge]: https://img.shields.io/npm/v/@formatjs/intl-pluralrules.svg?style=flat-square 32 | -------------------------------------------------------------------------------- /website/docs/tooling/ts-transformer.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ts-transformer 3 | title: ts-transformer 4 | --- 5 | 6 | [![npm version](https://badgen.net/npm/v/@formatjs/ts-transformer)](https://badgen.net/npm/v/@formatjs/ts-transformer) 7 | 8 | Extracts string messages for translation from modules that use React Intl (similar to [`babel-plugin-react-intl`](https://github.com/formatjs/formatjs/tree/master/packages/babel-plugin-react-intl)). 9 | 10 | Take a look at [`compile.ts`](compile.ts) for example in integration. 11 | -------------------------------------------------------------------------------- /website/lang/strings_cs-CZ.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "{takenDate, date, long} {name} {numPhotos, plural,=0 {nevyfotila} other {vyfotila} } {numPhotos, plural, =0 {žádnou fotku} one {jednu fotku} few {# fotky} other {# fotek}}." 3 | } -------------------------------------------------------------------------------- /website/lang/strings_en-US.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "{name} took {numPhotos, plural, =0 {no photos} =1 {one photo} other {# photos}} on {takenDate, date, long}." 3 | } -------------------------------------------------------------------------------- /website/lang/strings_es-AR.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "El {takenDate, date, long}, {name} {numPhotos, plural, =0 {no} other {} } sacó {numPhotos, plural, =0 {ninguna foto.} =1 {una foto.} other {# fotos.}}" 3 | } -------------------------------------------------------------------------------- /website/lang/strings_fr-FR.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "Le {takenDate, date, long}, {name} {numPhotos, plural, =0 {n'a pas pris de photographie.} =1 {a pris une photographie.} other {a pris # photographies.}}" 3 | } -------------------------------------------------------------------------------- /website/lang/strings_ja-JP.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "{name}は{takenDate, date, long}に{numPhotos, plural, =0 {1枚も写真を撮りませんでした。} =1 {1枚写真を撮りました。} other {#枚写真を撮りました。}}" 3 | } -------------------------------------------------------------------------------- /website/lang/strings_pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "Em {takenDate, date, long}, {name} {numPhotos, plural, =0 {não} other {} } tirou {numPhotos, plural, =0 {nenhuma foto.} =1 {uma foto.} other {# fotos.}}" 3 | } -------------------------------------------------------------------------------- /website/lang/strings_sv-SE.json: -------------------------------------------------------------------------------- 1 | { 2 | "demo": "{name} tog {numPhotos, plural, =0 {inte några foton} =1 {ett foto} other {# foton} } den {takenDate, date, long}." 3 | } -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "formatjs-website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "docusaurus start", 7 | "build": "docusaurus build", 8 | "swizzle": "docusaurus swizzle", 9 | "deploy": "docusaurus deploy" 10 | }, 11 | "dependencies": { 12 | "@docusaurus/core": "^2.0.0-alpha.48", 13 | "@docusaurus/preset-classic": "^2.0.0-alpha.48", 14 | "@docusaurus/theme-live-codeblock": "^2.0.0-alpha.39", 15 | "classnames": "^2.2.6", 16 | "react": "^16.8.4", 17 | "react-dom": "^16.8.4", 18 | "react-intl": "^4.5.0" 19 | }, 20 | "browserslist": { 21 | "production": [ 22 | ">0.2%", 23 | "not dead", 24 | "not op_mini all" 25 | ], 26 | "development": [ 27 | "last 1 chrome version", 28 | "last 1 firefox version", 29 | "last 1 safari version" 30 | ] 31 | }, 32 | "devDependencies": { 33 | "intl-messageformat-parser": "^5.0.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | docs: { 3 | 'Getting Started': [ 4 | 'basic-internationalization-principles', 5 | 'icu-syntax', 6 | 'runtime-requirements', 7 | ], 8 | Polyfills: [ 9 | 'polyfills', 10 | 'polyfills/intl-pluralrules', 11 | 'polyfills/intl-relativetimeformat', 12 | 'polyfills/intl-listformat', 13 | 'polyfills/intl-displaynames', 14 | 'polyfills/intl-numberformat', 15 | ], 16 | Libraries: [ 17 | 'intl-messageformat', 18 | 'intl-messageformat-parser', 19 | { 20 | type: 'category', 21 | label: 'react-intl', 22 | items: [ 23 | 'react-intl', 24 | 'react-intl/components', 25 | 'react-intl/api', 26 | 'react-intl/testing', 27 | 'react-intl/advanced-usage', 28 | 'react-intl/upgrade-guide-3x', 29 | 'react-intl/upgrade-guide-2x', 30 | ], 31 | }, 32 | ], 33 | Tooling: [ 34 | 'tooling/cli', 35 | 'tooling/linter', 36 | 'tooling/babel-plugin', 37 | 'tooling/ts-transformer', 38 | ], 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | :root { 10 | --ifm-color-primary: #25c2a0; 11 | --ifm-color-primary-dark: rgb(33, 175, 144); 12 | --ifm-color-primary-darker: rgb(31, 165, 136); 13 | --ifm-color-primary-darkest: rgb(26, 136, 112); 14 | --ifm-color-primary-light: rgb(70, 203, 174); 15 | --ifm-color-primary-lighter: rgb(102, 212, 189); 16 | --ifm-color-primary-lightest: rgb(146, 224, 208); 17 | --ifm-code-font-size: 95%; 18 | } 19 | 20 | .docusaurus-highlight-code-line { 21 | background-color: rgb(72, 77, 91); 22 | display: block; 23 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 24 | padding: 0 var(--ifm-pre-padding); 25 | } 26 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/img/chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/chrome.png -------------------------------------------------------------------------------- /website/static/img/edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/edge.png -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/firefox.png -------------------------------------------------------------------------------- /website/static/img/ie11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/ie11.png -------------------------------------------------------------------------------- /website/static/img/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /website/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /website/static/img/safari.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/safari.png -------------------------------------------------------------------------------- /website/static/img/splash-head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/formatjs/formatjs-old/d508962a57b9d4d82e3c3c40bf5b43547f1cc52d/website/static/img/splash-head.jpg --------------------------------------------------------------------------------