├── .babelrc ├── .codesandbox └── ci.json ├── .deepsource.toml ├── .eslintrc ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── example ├── app.js ├── greeter.js └── index.html ├── jest.config.js ├── package.json ├── sonar-project.properties ├── src ├── i18n-context.js ├── i18n.d.ts ├── i18n.js ├── i18n.test.js ├── index.d.ts ├── index.js ├── translate.d.ts ├── translate.js ├── useTranslate.d.ts └── useTranslate.js ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "sandboxes": ["px8n63v0m"] 3 | } 4 | -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = "test-coverage" 5 | enabled = true 6 | 7 | [[analyzers]] 8 | name = "javascript" 9 | enabled = true 10 | 11 | [analyzers.meta] 12 | plugins = ["react"] 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "jest": true 7 | }, 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:react/recommended", 11 | "plugin:prettier/recommended" 12 | ], 13 | "parserOptions": { 14 | "ecmaFeatures": { 15 | "experimentalObjectRestSpread": true, 16 | "jsx": true 17 | }, 18 | "sourceType": "module" 19 | }, 20 | "plugins": ["react", "react-hooks", "prettier"], 21 | "rules": { 22 | "react-hooks/rules-of-hooks": "error", 23 | "react-hooks/exhaustive-deps": "error", 24 | 25 | "prettier/prettier": "error" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | pull_request: 9 | types: [opened, synchronize, reopened] 10 | 11 | jobs: 12 | lint: 13 | name: Lint 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | 19 | - name: Get yarn cache directory path 20 | id: yarn-cache-dir-path 21 | run: echo "::set-output name=dir::$(yarn cache dir)" 22 | 23 | - name: Restore Lerna (Cache) 24 | uses: actions/cache@v2 25 | id: yarn-cache 26 | with: 27 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 28 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 29 | restore-keys: | 30 | ${{ runner.os }}-yarn- 31 | 32 | - name: Install Dependencies 33 | run: yarn --frozen-lockfile 34 | 35 | - name: Run Linters 36 | run: yarn lint 37 | 38 | test: 39 | name: Test 40 | runs-on: ubuntu-latest 41 | steps: 42 | - name: Checkout 43 | uses: actions/checkout@v2 44 | 45 | - name: Get yarn cache directory path 46 | id: yarn-cache-dir-path 47 | run: echo "::set-output name=dir::$(yarn cache dir)" 48 | 49 | - name: Restore Lerna (Cache) 50 | uses: actions/cache@v2 51 | id: yarn-cache 52 | with: 53 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 54 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 55 | restore-keys: | 56 | ${{ runner.os }}-yarn- 57 | 58 | - name: Install Dependencies 59 | run: yarn --frozen-lockfile 60 | 61 | - name: Run Tests 62 | run: yarn test 63 | 64 | - name: Fix Coverage Paths 65 | working-directory: ./coverage 66 | run: sed -i 's@'$GITHUB_WORKSPACE/'@/github/workspace/@g' lcov.info 67 | 68 | - name: SonarCloud Scan 69 | uses: SonarSource/sonarcloud-github-action@master 70 | env: 71 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 72 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 73 | 74 | # - name: Upload Coverage Report 75 | # uses: actions/upload-artifact@v2 76 | # with: 77 | # name: lcov-report 78 | # path: coverage/lcov.info 79 | 80 | - name: Send Coverage Report to Codacy 81 | run: bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r coverage/lcov.info 82 | env: 83 | CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} 84 | 85 | # sonarcloud: 86 | # name: SonarCloud 87 | # needs: test 88 | # runs-on: ubuntu-latest 89 | # steps: 90 | # - name: Download the Coverage Report 91 | # uses: actions/download-artifact@v2 92 | # with: 93 | # name: lcov-report 94 | # path: coverage/lcov.info 95 | # - uses: actions/checkout@v2 96 | # with: 97 | # fetch-depth: 0 98 | # - name: SonarCloud Scan 99 | # uses: SonarSource/sonarcloud-github-action@master 100 | # env: 101 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 102 | # SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 103 | -------------------------------------------------------------------------------- /.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 | # System files 40 | .DS_Store 41 | 42 | # Build directories 43 | lib 44 | example/dist.js 45 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | lib/ 3 | example/ 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | Thank you for considering to contribute. If you're looking for a way to get contributing, the best way is to look for a [Good first issue](https://github.com/nayaabkhan/react-polyglot/labels/good%20first%20issue). 4 | 5 | ## Setting up the project 6 | 7 | 1. Fork and clone the repo 8 | 2. `yarn` 9 | 3. `yarn test` 10 | 4. Use a branch for your PR: `git checkout -b your-branch-name` 11 | 12 | ## Commiting 13 | 14 | Please consider reading this [excellent guide](https://chris.beams.io/posts/git-commit/) for writing good commit messages. This is a convention that we aim to follow for this project. 15 | 16 | - Please keep unrelated changes in separate commits. 17 | - Keep related changes in the same commit. 18 | 19 | ## Before submitting a PR 20 | 21 | 1. Make sure that all tests pass. 22 | 2. Make sure you've updated type definitions, if required. 23 | 3. Make sure there are no breaking changes. 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Nayaabkhan Khan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | # React Polyglot 8 | Provides higher order component for using Polyglot with React 9 | 10 | ## Installation 11 | 12 | ``` 13 | npm install --save react-polyglot 14 | ``` 15 | 16 | ## Usage 17 | 18 | `react-polyglot` exports consists for one wrapper component called `I18n`, one decorator called 19 | `translate` and one hook called `useTranslate`. The decorator provides a prop `t` which is instance of `Polyglot`. 20 | 21 | You are required to wrap your root component with `I18n` and pass on a `locale` like `en` or `fr`. 22 | And `messages` object containing the strings. 23 | 24 | ```js 25 | import React from 'react'; 26 | import { render } from 'react-dom'; 27 | import { I18n } from 'react-polyglot'; 28 | import App from './components/app'; 29 | 30 | const locale = window.locale || 'en'; 31 | const messages = { 32 | "hello_name": "Hello, %{name}.", 33 | "num_cars": "%{smart_count} car |||| %{smart_count} cars", 34 | } 35 | 36 | render( 37 | 38 | 39 | , 40 | document.getElementById('app') 41 | ); 42 | ``` 43 | 44 | Then inside `App` or a child component of `App` you can do: 45 | 46 | ```js 47 | import React from 'react'; 48 | import { translate } from 'react-polyglot'; 49 | 50 | const Greeter = ({ name, t }) => ( 51 |

{t('hello_name', { name })}

52 | ); 53 | 54 | Greeter.propTypes = { 55 | name: React.PropTypes.string.isRequired, 56 | t: React.PropTypes.func.isRequired, 57 | }; 58 | 59 | export default translate()(Greeter); 60 | ``` 61 | 62 | 63 | or with React Hooks: 64 | 65 | ```js 66 | import React from 'react'; 67 | import { useTranslate } from 'react-polyglot'; 68 | 69 | export default const Greeter = ({ name }) => { 70 | const t = useTranslate(); 71 | 72 | return ( 73 |

{t('hello_name', { name })}

74 | ); 75 | }; 76 | 77 | Greeter.propTypes = { 78 | name: React.PropTypes.string.isRequired 79 | }; 80 | 81 | ``` 82 | 83 | 84 | ## Live Examples 85 | 86 | ### Minimal example using class components 87 | 88 | https://codesandbox.io/s/mq76ojk228 89 | 90 | ### Advance example with user changeable locales 91 | 92 | https://codesandbox.io/s/px8n63v0m 93 | 94 | 95 | ## How to provide context in your tests 96 | 97 | Use a simple helper to wrap your components in a context. 98 | 99 | ```js 100 | export const wrapWithContext = function (component, context, contextTypes) { 101 | const wrappedComponent = React.createClass({ 102 | childContextTypes: contextTypes, 103 | getChildContext() { 104 | return context; 105 | }, 106 | render() { 107 | return component; 108 | }, 109 | }); 110 | return React.createElement(wrappedComponent); 111 | } 112 | ``` 113 | 114 | Then use it inside your tests. 115 | 116 | ```js 117 | import React from 'react'; 118 | import { renderToString } from 'react-dom/server'; 119 | import Polyglot from 'node-polyglot'; 120 | import Greeter from './greeter'; 121 | import { wrapWithContext } from './helpers'; 122 | 123 | const polyglot = new Polyglot({ 124 | locale: 'en', 125 | phrases: {"hello_name": "Hello, %{name}."}, 126 | }); 127 | 128 | const greeterWithContext = wrapWithContext( 129 | , 130 | { t: polyglot.t.bind(polyglot) }, 131 | { t: React.PropTypes.func } 132 | ); 133 | 134 | // use greeterWithContext in your tests 135 | // here it is shown how to use it with renderToString 136 | console.log(renderToString(greeterWithContext)); 137 | ``` 138 | 139 | 140 | ## Release History 141 | 142 | Check the [Releases](https://github.com/nayaabkhan/react-polyglot/releases) tab. 143 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { I18n } from '../lib'; 4 | import Greeter from './greeter'; 5 | 6 | const locale = window.locale || 'en'; 7 | const messages = { 8 | "hello_name": "Hello, %{name}.", 9 | "num_cars": "%{smart_count} car |||| %{smart_count} cars", 10 | } 11 | 12 | render( 13 | 14 | 15 | , 16 | document.getElementById('app') 17 | ); 18 | -------------------------------------------------------------------------------- /example/greeter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { translate } from '../lib'; 3 | 4 | const Greeter = ({ name, t }) => ( 5 |

{t('hello_name', { name })}

6 | ); 7 | 8 | export default translate()(Greeter); 9 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | react-polygot demo 5 | 6 | 7 |
8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // For a detailed explanation regarding each configuration property, visit: 2 | // https://jestjs.io/docs/en/configuration.html 3 | 4 | module.exports = { 5 | collectCoverage: true, 6 | collectCoverageFrom: ['src/**/*.{js,jsx}'], 7 | coverageDirectory: 'coverage', 8 | coveragePathIgnorePatterns: ['/node_modules/', 'lib'], 9 | testEnvironment: 'node', 10 | } 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-polyglot", 3 | "version": "0.7.1", 4 | "description": "Higher order React component for using Polyglot", 5 | "main": "lib/index.js", 6 | "files": [ 7 | "lib", 8 | "src", 9 | "example" 10 | ], 11 | "types": "src/index.d.ts", 12 | "scripts": { 13 | "clean": "rimraf lib", 14 | "build:example": "webpack example/app.js example/dist.js", 15 | "build:commonjs": "babel src --out-dir lib --ignore '*.test.js'", 16 | "build": "npm run build:commonjs", 17 | "prepublish": "npm run clean && npm run build", 18 | "prettify": "prettier 'src/**/*.js' --write", 19 | "lint": "eslint src", 20 | "test": "jest" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/nayaabkhan/react-polyglot.git" 25 | }, 26 | "keywords": [ 27 | "react", 28 | "airbnb", 29 | "polyglot", 30 | "i18n" 31 | ], 32 | "author": "Nayaabkhan Khan (http://nayaabkhan.me)", 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/nayaabkhan/react-polyglot/issues" 36 | }, 37 | "homepage": "https://github.com/nayaabkhan/react-polyglot#readme", 38 | "peerDependencies": { 39 | "node-polyglot": "^2.0.0", 40 | "react": ">=16.8.0" 41 | }, 42 | "devDependencies": { 43 | "@babel/cli": "^7.7.0", 44 | "@babel/core": "^7.7.0", 45 | "@babel/preset-env": "^7.7.1", 46 | "@babel/preset-react": "^7.7.0", 47 | "babel-eslint": "^10.0.3", 48 | "babel-loader": "^8.0.6", 49 | "eslint": "^6.6.0", 50 | "eslint-config-prettier": "^6.5.0", 51 | "eslint-plugin-prettier": "^3.1.1", 52 | "eslint-plugin-react": "^7.7.0", 53 | "eslint-plugin-react-hooks": "^2.2.0", 54 | "jest": "^24.9.0", 55 | "node-polyglot": "^2.2.2", 56 | "prettier": "^1.18.2", 57 | "react": "^16.3.2", 58 | "react-dom": "^16.3.2", 59 | "react-test-renderer": "^16.3.2", 60 | "rimraf": "^2.5.4", 61 | "webpack": "^4.41.2" 62 | }, 63 | "dependencies": { 64 | "hoist-non-react-statics": "^3.3.0", 65 | "prop-types": "^15.5.8" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=nayaabkhan_react-polyglot 2 | sonar.organization=nayaabkhan 3 | 4 | sonar.javascript.lcov.reportPaths=coverage/lcov.info 5 | 6 | # This is the name and version displayed in the SonarCloud UI. 7 | #sonar.projectName=react-polyglot 8 | #sonar.projectVersion=1.0 9 | 10 | # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. 11 | #sonar.sources=. 12 | 13 | # Encoding of the source code. Default is default system encoding 14 | #sonar.sourceEncoding=UTF-8 15 | -------------------------------------------------------------------------------- /src/i18n-context.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const I18nContext = React.createContext() 4 | 5 | export default I18nContext 6 | -------------------------------------------------------------------------------- /src/i18n.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for react-polyglot v0.4.0 2 | // TypeScript Version: 2.8 3 | 4 | import { ComponentType, ReactNode } from 'react' 5 | 6 | interface InterpolationOptions { 7 | smart_count?: number | { length: number }; 8 | _?: string; 9 | [interpolationKey: string]: any; 10 | } 11 | 12 | interface InterpolationTokenOptions { 13 | prefix?: string; 14 | suffix?: string; 15 | } 16 | 17 | interface PluralRules { 18 | pluralTypes: { 19 | [key: string]: (no: number) => number; 20 | }; 21 | pluralTypeToLanguages: { 22 | [key: string]: string[]; 23 | }; 24 | } 25 | 26 | interface PolyglotOptions { 27 | /** Locale to use, e.g. `en` */ 28 | locale: string; 29 | /** A dictionary of translations */ 30 | messages: object; 31 | 32 | /** A boolean to control whether missing keys are allowed **/ 33 | allowMissing?: boolean; 34 | /** If allow missing is true this function will be called instead of default error handler **/ 35 | onMissingKey?: (key: string, options?: InterpolationOptions, locale?: string) => string; 36 | /** An object to change the substituation syntax for interpolation by setting prefix and suffix **/ 37 | interpolation?: InterpolationTokenOptions; 38 | /** https://github.com/airbnb/polyglot.js#custom-pluralization-rules */ 39 | pluralRules?: PluralRules; 40 | } 41 | 42 | interface I18nProps extends PolyglotOptions { 43 | children: ReactNode; 44 | } 45 | 46 | /** Provider component to wrap your root application component in. */ 47 | declare const I18n: ComponentType 48 | 49 | export default I18n 50 | -------------------------------------------------------------------------------- /src/i18n.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import Polyglot from 'node-polyglot' 4 | import I18nContext from './i18n-context' 5 | 6 | export default function I18n({ 7 | locale, 8 | messages, 9 | 10 | allowMissing, 11 | onMissingKey, 12 | interpolation, 13 | pluralRules, 14 | 15 | children, 16 | }) { 17 | const translate = React.useMemo(() => { 18 | const polyglot = new Polyglot({ 19 | locale, 20 | phrases: messages, 21 | 22 | allowMissing, 23 | onMissingKey, 24 | interpolation, 25 | pluralRules, 26 | }) 27 | const boundTranslate = polyglot.t.bind(polyglot) 28 | 29 | boundTranslate._polyglot = polyglot 30 | 31 | return boundTranslate 32 | }, [locale, messages, allowMissing, onMissingKey, interpolation, pluralRules]) 33 | 34 | return ( 35 | 36 | {React.Children.only(children)} 37 | 38 | ) 39 | } 40 | 41 | I18n.propTypes = { 42 | locale: PropTypes.string.isRequired, 43 | messages: PropTypes.object.isRequired, 44 | 45 | allowMissing: PropTypes.bool, 46 | onMissingKey: PropTypes.func, 47 | interpolation: PropTypes.shape({ 48 | suffix: PropTypes.string, 49 | prefix: PropTypes.string, 50 | }), 51 | pluralRules: PropTypes.shape({ 52 | pluralTypes: PropTypes.object, 53 | pluralTypeToLanguages: PropTypes.object, 54 | }), 55 | 56 | children: PropTypes.element.isRequired, 57 | } 58 | 59 | I18n.defaultProps = { 60 | allowMissing: false, 61 | onMissingKey: undefined, 62 | interpolation: undefined, 63 | pluralRules: undefined, 64 | } 65 | -------------------------------------------------------------------------------- /src/i18n.test.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import TestRenderer from 'react-test-renderer' 3 | import I18n from './i18n' 4 | import I18nContext from './i18n-context' 5 | 6 | describe('I18n Provider', () => { 7 | const createChild = () => { 8 | class Child extends Component { 9 | render() { 10 | return
11 | } 12 | } 13 | 14 | return Child 15 | } 16 | const Child = createChild() 17 | 18 | function getPolyglotFromRenderer(renderer) { 19 | const instance = renderer.root 20 | const children = instance.children 21 | const firstChild = children[0] 22 | const firstChildValueProps = firstChild.props.value 23 | const polyglot = firstChildValueProps._polyglot 24 | 25 | return polyglot 26 | } 27 | 28 | it('should update instance on receiving new props', () => { 29 | const props = { 30 | locale: 'en', 31 | messages: { 32 | test: 'test', 33 | }, 34 | } 35 | 36 | const renderer = TestRenderer.create( 37 | 38 | 39 | {value => { 40 | return 41 | }} 42 | 43 | 44 | ) 45 | 46 | const newProps = { 47 | locale: 'jp', 48 | messages: { 49 | test: 'test', 50 | }, 51 | } 52 | 53 | renderer.update( 54 | 55 | 56 | {value => { 57 | return 58 | }} 59 | 60 | 61 | ) 62 | 63 | const polyglot = getPolyglotFromRenderer(renderer) 64 | 65 | expect(polyglot.locale()).toBe('jp') 66 | }) 67 | }) 68 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | export { default as I18n } from './i18n'; 2 | export { default as translate } from './translate'; 3 | export { default as useTranslate} from './useTranslate'; 4 | export * from './translate'; 5 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import I18n from './i18n' 2 | import translate from './translate' 3 | import useTranslate from './useTranslate' 4 | 5 | export { I18n, translate, useTranslate } 6 | -------------------------------------------------------------------------------- /src/translate.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for react-polyglot v0.4.0 2 | // Typescript version: 2.8 3 | 4 | import { InterpolationOptions } from 'node-polyglot' 5 | import { ComponentType } from 'react' 6 | 7 | export type t = ( 8 | /** The key of the phrase to translate. */ 9 | phrase: string, 10 | /** The options accepted by `polyglot.t`. */ 11 | options?: number | InterpolationOptions 12 | ) => string 13 | 14 | export interface TranslateProps { 15 | /** Function to get translated phrase. */ 16 | t: t 17 | } 18 | 19 | /** Wrap your components with `translate` to get a prop `t` passed in. */ 20 | declare const translate = () => ( 21 | Component: ComponentType 22 | ) => ComponentType(Component) 23 | 24 | export default translate 25 | -------------------------------------------------------------------------------- /src/translate.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import hoistNonReactStatics from 'hoist-non-react-statics' 3 | import I18nContext from './i18n-context' 4 | 5 | // higher order decorator for components that need `t` 6 | export default function translate() { 7 | return WrappedComponent => { 8 | const _translate = props => ( 9 | 10 | {t => } 11 | 12 | ) 13 | 14 | return hoistNonReactStatics(_translate, WrappedComponent) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/useTranslate.d.ts: -------------------------------------------------------------------------------- 1 | import { InterpolationOptions } from 'node-polyglot' 2 | 3 | type TranslateFunction = ( 4 | phrase: string, 5 | options?: number| InterpolationOptions 6 | ) => string 7 | 8 | declare const useTranslate = () => TranslateFunction 9 | 10 | export default useTranslate 11 | -------------------------------------------------------------------------------- /src/useTranslate.js: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react' 2 | import I18nContext from './i18n-context' 3 | 4 | export default function useTranslate() { 5 | return useContext(I18nContext) 6 | } 7 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack') 2 | 3 | var env = process.env.NODE_ENV 4 | 5 | var config = { 6 | module: { 7 | loaders: [ 8 | { test: /\.js$/, loaders: ['babel-loader'], exclude: /node_modules/ }, 9 | ], 10 | }, 11 | 12 | plugins: [ 13 | new webpack.optimize.OccurenceOrderPlugin(), 14 | new webpack.DefinePlugin({ 15 | 'process.env.NODE_ENV': JSON.stringify(env), 16 | }), 17 | ], 18 | } 19 | 20 | module.exports = config 21 | --------------------------------------------------------------------------------