cozy-ui 134.2.0 → 135.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/package.json +4 -2
- package/react/ActionsBar/index.jsx +1 -1
- package/react/ActionsBar/locales/withActionsLocales.jsx +2 -1
- package/react/ActionsMenu/Actions/locales/withActionsLocales.jsx +2 -2
- package/react/ActionsMenu/ActionsItems.jsx +1 -1
- package/react/ActionsMenu/ActionsMenuButton.jsx +1 -1
- package/react/CozyDialogs/DialogBackButton.jsx +1 -1
- package/react/CozyDialogs/DialogCloseButton.jsx +1 -1
- package/react/CozyDialogs/SpecificDialogs/AllowLocationDialog.jsx +1 -1
- package/react/CozyDialogs/SpecificDialogs/InstallFlagshipAppDialog.jsx +1 -1
- package/react/CozyDialogs/SpecificDialogs/ShortcutDialog.jsx +1 -1
- package/react/CozyDialogs/SpecificDialogs/withSpecificDialogsLocales.jsx +2 -1
- package/react/DateMonthPicker/Readme.md +1 -1
- package/react/DateMonthPicker/index.jsx +1 -1
- package/react/DateMonthPicker/index.spec.jsx +1 -1
- package/react/DatePicker/index.jsx +1 -1
- package/react/DatePicker/locales/withOwnLocales.jsx +2 -1
- package/react/EditBadge/EditMenu.jsx +1 -1
- package/react/Labs/PasswordInput/index.jsx +1 -1
- package/react/Nav/index.jsx +1 -1
- package/react/Nav/locales/withNavLocales.jsx +2 -1
- package/react/PasswordField/index.jsx +1 -2
- package/react/SearchBar/index.jsx +1 -1
- package/react/SearchBar/locales/withOnlyLocales.jsx +2 -1
- package/react/SelectionBar/SelectionBarAction.jsx +1 -1
- package/react/SelectionBar/SelectionBarMore.jsx +1 -1
- package/react/SelectionBar/index.jsx +1 -1
- package/react/Spinner/Readme.md +1 -1
- package/react/Spinner/index.jsx +1 -1
- package/react/Table/Virtualized/Dnd/TableRow.jsx +1 -2
- package/react/Wizard/index.jsx +1 -1
- package/react/deprecated/ActionMenu/Actions/ActionsItems.jsx +1 -1
- package/react/deprecated/ActionMenu/Actions/call.js +1 -1
- package/react/deprecated/ActionMenu/Actions/emailTo.js +1 -1
- package/react/deprecated/ActionMenu/Actions/locales/withActionsLocales.jsx +2 -1
- package/react/deprecated/ActionMenu/Actions/smsTo.js +1 -1
- package/react/hooks/useConfirmExit/index.jsx +1 -1
- package/react/index.js +0 -1
- package/react/jestLib/I18n.js +1 -1
- package/react/providers/DemoProvider.jsx +1 -1
- package/transpiled/react/ActionsBar/index.js +1 -1
- package/transpiled/react/ActionsBar/locales/withActionsLocales.js +1 -1
- package/transpiled/react/ActionsMenu/Actions/locales/withActionsLocales.d.ts +1 -1
- package/transpiled/react/ActionsMenu/Actions/locales/withActionsLocales.js +1 -2
- package/transpiled/react/ActionsMenu/ActionsItems.js +1 -1
- package/transpiled/react/ActionsMenu/ActionsMenuButton.js +1 -1
- package/transpiled/react/CozyDialogs/DialogBackButton.js +1 -1
- package/transpiled/react/CozyDialogs/DialogCloseButton.js +1 -1
- package/transpiled/react/CozyDialogs/SpecificDialogs/AllowLocationDialog.js +1 -1
- package/transpiled/react/CozyDialogs/SpecificDialogs/InstallFlagshipAppDialog.js +1 -1
- package/transpiled/react/CozyDialogs/SpecificDialogs/ShortcutDialog.js +1 -1
- package/transpiled/react/CozyDialogs/SpecificDialogs/withSpecificDialogsLocales.js +1 -1
- package/transpiled/react/DateMonthPicker/index.js +1 -1
- package/transpiled/react/DatePicker/index.js +1 -1
- package/transpiled/react/DatePicker/locales/withOwnLocales.js +1 -1
- package/transpiled/react/EditBadge/EditMenu.js +1 -1
- package/transpiled/react/Labs/PasswordInput/index.js +1 -1
- package/transpiled/react/Nav/index.js +1 -1
- package/transpiled/react/Nav/locales/withNavLocales.js +1 -1
- package/transpiled/react/PasswordField/index.js +1 -2
- package/transpiled/react/SearchBar/index.js +1 -1
- package/transpiled/react/SearchBar/locales/withOnlyLocales.js +1 -1
- package/transpiled/react/SelectionBar/SelectionBarAction.js +1 -1
- package/transpiled/react/SelectionBar/SelectionBarMore.js +1 -1
- package/transpiled/react/SelectionBar/index.js +1 -1
- package/transpiled/react/Spinner/index.js +1 -1
- package/transpiled/react/Table/Virtualized/Dnd/TableRow.js +1 -1
- package/transpiled/react/Wizard/index.js +1 -1
- package/transpiled/react/deprecated/ActionMenu/Actions/ActionsItems.js +1 -1
- package/transpiled/react/deprecated/ActionMenu/Actions/call.js +1 -1
- package/transpiled/react/deprecated/ActionMenu/Actions/emailTo.js +1 -1
- package/transpiled/react/deprecated/ActionMenu/Actions/locales/withActionsLocales.js +1 -1
- package/transpiled/react/deprecated/ActionMenu/Actions/smsTo.js +1 -1
- package/transpiled/react/hooks/useConfirmExit/index.js +1 -1
- package/transpiled/react/index.d.ts +0 -1
- package/transpiled/react/index.js +0 -1
- package/transpiled/react/jestLib/I18n.d.ts +1 -1
- package/transpiled/react/jestLib/I18n.js +1 -1
- package/transpiled/react/providers/DemoProvider.js +1 -1
- package/react/I18n/index.js +0 -25
- package/react/I18n/withLocales.js +0 -14
- package/react/providers/I18n/createUseI18n.jsx +0 -32
- package/react/providers/I18n/format.jsx +0 -62
- package/react/providers/I18n/format.spec.jsx +0 -73
- package/react/providers/I18n/helpers.js +0 -33
- package/react/providers/I18n/index.jsx +0 -107
- package/react/providers/I18n/index.spec.jsx +0 -135
- package/react/providers/I18n/translate.jsx +0 -28
- package/react/providers/I18n/translation.jsx +0 -42
- package/react/providers/I18n/useExtendI18n.jsx +0 -37
- package/react/providers/I18n/withLocales.jsx +0 -47
- package/react/providers/I18n/withLocales.spec.jsx +0 -58
- package/react/providers/I18n/withOnlyLocales.jsx +0 -38
- package/transpiled/react/I18n/index.d.ts +0 -3
- package/transpiled/react/I18n/index.js +0 -16
- package/transpiled/react/I18n/withLocales.d.ts +0 -2
- package/transpiled/react/I18n/withLocales.js +0 -10
- package/transpiled/react/providers/I18n/createUseI18n.d.ts +0 -6
- package/transpiled/react/providers/I18n/createUseI18n.js +0 -39
- package/transpiled/react/providers/I18n/format.d.ts +0 -3
- package/transpiled/react/providers/I18n/format.js +0 -72
- package/transpiled/react/providers/I18n/format.spec.d.ts +0 -1
- package/transpiled/react/providers/I18n/helpers.d.ts +0 -5
- package/transpiled/react/providers/I18n/helpers.js +0 -35
- package/transpiled/react/providers/I18n/index.d.ts +0 -62
- package/transpiled/react/providers/I18n/index.js +0 -132
- package/transpiled/react/providers/I18n/index.spec.d.ts +0 -1
- package/transpiled/react/providers/I18n/translate.d.ts +0 -3
- package/transpiled/react/providers/I18n/translate.js +0 -21
- package/transpiled/react/providers/I18n/translation.d.ts +0 -3
- package/transpiled/react/providers/I18n/translation.js +0 -40
- package/transpiled/react/providers/I18n/useExtendI18n.d.ts +0 -7
- package/transpiled/react/providers/I18n/useExtendI18n.js +0 -42
- package/transpiled/react/providers/I18n/withLocales.d.ts +0 -8
- package/transpiled/react/providers/I18n/withLocales.js +0 -69
- package/transpiled/react/providers/I18n/withLocales.spec.d.ts +0 -1
- package/transpiled/react/providers/I18n/withOnlyLocales.d.ts +0 -8
- package/transpiled/react/providers/I18n/withOnlyLocales.js +0 -39
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { initFormat, formatLocallyDistanceToNow } from './format'
|
|
2
|
-
|
|
3
|
-
describe('initFormat', () => {
|
|
4
|
-
beforeEach(() => {
|
|
5
|
-
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
|
6
|
-
})
|
|
7
|
-
|
|
8
|
-
afterEach(() => {
|
|
9
|
-
console.warn.mockRestore()
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
it('should not throw if a date-fns locale can not be found', () => {
|
|
13
|
-
expect(() => initFormat('unknown-lang', 'unknown-default')).not.toThrow()
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('should use the correct locale', () => {
|
|
17
|
-
const f = initFormat('fr', 'en')
|
|
18
|
-
const date = f(0, 'yyyy-LLLL-dd')
|
|
19
|
-
expect(date).toBe('1970-janvier-01')
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('should use the correct default locale if user locale can not be found', () => {
|
|
23
|
-
const f = initFormat('it', 'fr')
|
|
24
|
-
const date = f(0, 'yyyy-LLLL-dd')
|
|
25
|
-
expect(date).toBe('1970-janvier-01')
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
it('should fallback english if user locale and default locale can not be found', () => {
|
|
29
|
-
const f = initFormat('unknown-lang', 'unknown-default')
|
|
30
|
-
const date = f(0, 'yyyy-LLLL-dd')
|
|
31
|
-
expect(date).toBe('1970-January-01')
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
describe('formatLocallyDistanceToNow', () => {
|
|
36
|
-
beforeEach(() => {
|
|
37
|
-
// To avoid currentLocale set to 'fr' because of previous tests
|
|
38
|
-
const f = initFormat('en')
|
|
39
|
-
f(0, 'yyyy-LLLL-dd')
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('should formatDistanceToNow with small value', () => {
|
|
43
|
-
const date = Date.now() + 29 * 1000 // 29s
|
|
44
|
-
|
|
45
|
-
const result = formatLocallyDistanceToNow(date)
|
|
46
|
-
|
|
47
|
-
expect(result).toEqual('less than a minute')
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('should formatDistanceToNow with medium value', () => {
|
|
51
|
-
const date = Date.now() + (44 * 60 + 31) * 1000 // 44min 31s
|
|
52
|
-
|
|
53
|
-
const result = formatLocallyDistanceToNow(date)
|
|
54
|
-
|
|
55
|
-
expect(result).toEqual('about 1 hour')
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
it('should formatDistanceToNow with high value', () => {
|
|
59
|
-
const date = Date.now() + (89 * 60 + 31) * 1000 // 89min 31s
|
|
60
|
-
|
|
61
|
-
const result = formatLocallyDistanceToNow(date)
|
|
62
|
-
|
|
63
|
-
expect(result).toEqual('about 2 hours')
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('should formatDistanceToNow with very high value', () => {
|
|
67
|
-
const date = Date.now() + 42 * 24 * 60 * 60 * 1000 // 42d
|
|
68
|
-
|
|
69
|
-
const result = formatLocallyDistanceToNow(date)
|
|
70
|
-
|
|
71
|
-
expect(result).toEqual('about 1 month')
|
|
72
|
-
})
|
|
73
|
-
})
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_LANG } from './'
|
|
2
|
-
import { initFormat } from './format'
|
|
3
|
-
import { initTranslation } from './translation'
|
|
4
|
-
|
|
5
|
-
const getAppOrUiLang = defaultLang => {
|
|
6
|
-
const appContainer = document.querySelector('[role=application]')
|
|
7
|
-
const cozyUiContainer = {
|
|
8
|
-
dataset: {
|
|
9
|
-
cozy: JSON.stringify({
|
|
10
|
-
locale: localStorage.getItem('lang') || defaultLang
|
|
11
|
-
})
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
const container = appContainer || cozyUiContainer
|
|
15
|
-
const { locale } = JSON.parse(container.dataset.cozy)
|
|
16
|
-
|
|
17
|
-
return /^\{\{\..*\}\}$/.test(locale) ? defaultLang : locale
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export const getI18n = (
|
|
21
|
-
lang,
|
|
22
|
-
dictRequire,
|
|
23
|
-
context,
|
|
24
|
-
defaultLang = DEFAULT_LANG
|
|
25
|
-
) => {
|
|
26
|
-
const _lang = lang || getAppOrUiLang(defaultLang)
|
|
27
|
-
const polyglot = initTranslation(_lang, dictRequire, context, defaultLang)
|
|
28
|
-
|
|
29
|
-
const f = initFormat(_lang)
|
|
30
|
-
const t = polyglot.t.bind(polyglot)
|
|
31
|
-
|
|
32
|
-
return { t, f, lang: _lang }
|
|
33
|
-
}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provides an I18n helper using a Higher Order Component.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
'use strict'
|
|
6
|
-
|
|
7
|
-
import PropTypes from 'prop-types'
|
|
8
|
-
import React, { Component, useContext } from 'react'
|
|
9
|
-
|
|
10
|
-
import { initFormat } from './format'
|
|
11
|
-
import { initTranslation } from './translation'
|
|
12
|
-
|
|
13
|
-
export const DEFAULT_LANG = 'en'
|
|
14
|
-
|
|
15
|
-
export const I18nContext = React.createContext()
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* @typedef useI18nReturnTypes
|
|
19
|
-
* @property {(key: string) => string} t
|
|
20
|
-
* @property {(date: string, format: string) => string} f
|
|
21
|
-
* @property {string} lang
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @returns {useI18nReturnTypes}
|
|
26
|
-
*/
|
|
27
|
-
export const useI18n = () => {
|
|
28
|
-
const context = useContext(I18nContext)
|
|
29
|
-
|
|
30
|
-
if (!context) {
|
|
31
|
-
throw new Error(
|
|
32
|
-
'`I18nContext` is missing. `useI18n()` must be used within a `<I18n>`'
|
|
33
|
-
)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return context
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Provider root component
|
|
40
|
-
export class I18n extends Component {
|
|
41
|
-
constructor(props) {
|
|
42
|
-
super(props)
|
|
43
|
-
this.init(this.props)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
init(props) {
|
|
47
|
-
const { polyglot, lang, dictRequire, context, defaultLang } = props
|
|
48
|
-
this.translator =
|
|
49
|
-
polyglot || initTranslation(lang, dictRequire, context, defaultLang)
|
|
50
|
-
this.format = initFormat(lang, defaultLang)
|
|
51
|
-
this.t = this.translator.t.bind(this.translator)
|
|
52
|
-
this.contextValue = this.getContextValue(props)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
getContextValue(props) {
|
|
56
|
-
return {
|
|
57
|
-
t: this.t,
|
|
58
|
-
f: this.format,
|
|
59
|
-
polyglot: (props || this.props).polyglot || this.translator,
|
|
60
|
-
lang: (props || this.props).lang
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
getChildContext() {
|
|
65
|
-
return this.contextValue
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
UNSAFE_componentWillReceiveProps = nextProps => {
|
|
69
|
-
if (nextProps.lang !== this.props.lang) {
|
|
70
|
-
this.init(nextProps)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
render() {
|
|
75
|
-
return (
|
|
76
|
-
<I18nContext.Provider value={this.contextValue}>
|
|
77
|
-
{this.props.children}
|
|
78
|
-
</I18nContext.Provider>
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
I18n.propTypes = {
|
|
84
|
-
lang: PropTypes.string.isRequired, // current language.
|
|
85
|
-
polyglot: PropTypes.object, // A polyglot instance.
|
|
86
|
-
dictRequire: PropTypes.func, // A callback to load locales.
|
|
87
|
-
context: PropTypes.string, // current context.
|
|
88
|
-
defaultLang: PropTypes.string // default language. By default is 'en'
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
I18n.defaultProps = {
|
|
92
|
-
defaultLang: DEFAULT_LANG
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
I18n.childContextTypes = {
|
|
96
|
-
t: PropTypes.func,
|
|
97
|
-
f: PropTypes.func,
|
|
98
|
-
polyglot: PropTypes.object,
|
|
99
|
-
lang: PropTypes.string
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export { initTranslation, extend } from './translation'
|
|
103
|
-
export { default as translate } from './translate'
|
|
104
|
-
export { default as createUseI18n } from './createUseI18n'
|
|
105
|
-
export { default as useExtendI18n } from './useExtendI18n'
|
|
106
|
-
|
|
107
|
-
export default I18n
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { render, fireEvent, screen } from '@testing-library/react'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
|
-
import React, { useState } from 'react'
|
|
4
|
-
|
|
5
|
-
import I18n, { useI18n, createUseI18n } from '.'
|
|
6
|
-
|
|
7
|
-
const locales = { helloworld: 'Hello World !' }
|
|
8
|
-
|
|
9
|
-
const DumbI18nHelloWorld = ({ t, f, lang }) => (
|
|
10
|
-
<div>
|
|
11
|
-
{t('helloworld')}
|
|
12
|
-
<br />
|
|
13
|
-
{f('2020-01-06', 'D LLL', { useAdditionalDayOfYearTokens: true })}
|
|
14
|
-
<br />
|
|
15
|
-
{lang}
|
|
16
|
-
</div>
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
const I18nHelloWorldHook = () => {
|
|
20
|
-
const { t, f, lang } = useI18n()
|
|
21
|
-
return <DumbI18nHelloWorld t={t} f={f} lang={lang} />
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const I18nHelloWorldOldAPI = (props, context) => {
|
|
25
|
-
const { t, f, lang } = context
|
|
26
|
-
return <DumbI18nHelloWorld t={t} f={f} lang={lang} />
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
I18nHelloWorldOldAPI.contextTypes = {
|
|
30
|
-
t: PropTypes.func,
|
|
31
|
-
f: PropTypes.func,
|
|
32
|
-
lang: PropTypes.string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
describe('new context api', () => {
|
|
36
|
-
it('should provide t and f and lang through useI18n hook', () => {
|
|
37
|
-
render(
|
|
38
|
-
<I18n lang="en" dictRequire={() => locales}>
|
|
39
|
-
<I18nHelloWorldHook />
|
|
40
|
-
</I18n>
|
|
41
|
-
)
|
|
42
|
-
expect(
|
|
43
|
-
screen.getByText('Hello World !', { exact: false })
|
|
44
|
-
).toBeInTheDocument()
|
|
45
|
-
expect(screen.getByText('6 Jan', { exact: false })).toBeInTheDocument()
|
|
46
|
-
expect(screen.getByText('en', { exact: false })).toBeInTheDocument()
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
describe('old context api', () => {
|
|
51
|
-
it('should provide t and f and lang through old context API', () => {
|
|
52
|
-
render(
|
|
53
|
-
<I18n lang="en" dictRequire={() => locales}>
|
|
54
|
-
<I18nHelloWorldOldAPI />
|
|
55
|
-
</I18n>
|
|
56
|
-
)
|
|
57
|
-
expect(
|
|
58
|
-
screen.getByText('Hello World !', { exact: false })
|
|
59
|
-
).toBeInTheDocument()
|
|
60
|
-
expect(screen.getByText('6 Jan', { exact: false })).toBeInTheDocument()
|
|
61
|
-
expect(screen.getByText('en', { exact: false })).toBeInTheDocument()
|
|
62
|
-
})
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
describe('use i18n with custom locales', () => {
|
|
66
|
-
const locales = {
|
|
67
|
-
en: {
|
|
68
|
-
'hello-world': 'Hello world'
|
|
69
|
-
},
|
|
70
|
-
fr: {
|
|
71
|
-
'hello-world': 'Bonjour le monde'
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const useI18n = createUseI18n(locales)
|
|
75
|
-
const Child = () => {
|
|
76
|
-
const { t } = useI18n()
|
|
77
|
-
return <div>{t('hello-world')}</div>
|
|
78
|
-
}
|
|
79
|
-
const Parent = () => {
|
|
80
|
-
const [lang, setLang] = useState('en')
|
|
81
|
-
return (
|
|
82
|
-
<>
|
|
83
|
-
<button onClick={() => setLang('fr')}>switch to French</button>
|
|
84
|
-
<I18n lang={lang} dictRequire={() => ({})}>
|
|
85
|
-
<Child />
|
|
86
|
-
</I18n>
|
|
87
|
-
</>
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
it('should work', () => {
|
|
92
|
-
const root = render(<Parent />)
|
|
93
|
-
const btn = root.getByText('switch to French')
|
|
94
|
-
expect(root.getByText('Hello world')).toBeTruthy()
|
|
95
|
-
fireEvent.click(btn)
|
|
96
|
-
expect(root.getByText('Bonjour le monde')).toBeTruthy()
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
describe('use i18n with custom locales and fallback to default', () => {
|
|
101
|
-
const locales = {
|
|
102
|
-
en: {
|
|
103
|
-
'hello-world': 'Hello world',
|
|
104
|
-
'how-are-you': 'How are you ?'
|
|
105
|
-
},
|
|
106
|
-
fr: {
|
|
107
|
-
'hello-world': 'Bonjour le monde'
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const useI18n = createUseI18n(locales)
|
|
111
|
-
const Child = () => {
|
|
112
|
-
const { t } = useI18n()
|
|
113
|
-
return (
|
|
114
|
-
<div>
|
|
115
|
-
<div>{t('hello-world')}</div>
|
|
116
|
-
<div>{t('how-are-you')}</div>
|
|
117
|
-
</div>
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
const Parent = () => {
|
|
121
|
-
return (
|
|
122
|
-
<>
|
|
123
|
-
<I18n lang="fr" dictRequire={() => ({})}>
|
|
124
|
-
<Child />
|
|
125
|
-
</I18n>
|
|
126
|
-
</>
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
it('should display missing key in default langage', () => {
|
|
131
|
-
const root = render(<Parent />)
|
|
132
|
-
expect(root.getByText('Bonjour le monde')).toBeInTheDocument()
|
|
133
|
-
expect(root.getByText('How are you ?')).toBeInTheDocument()
|
|
134
|
-
})
|
|
135
|
-
})
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React, { useContext, forwardRef } from 'react'
|
|
2
|
-
|
|
3
|
-
import { I18nContext } from '.'
|
|
4
|
-
|
|
5
|
-
// higher order decorator for components that need `t` and/or `f`
|
|
6
|
-
const translate = () => WrappedComponent => {
|
|
7
|
-
const Wrapper = forwardRef((props, ref) => {
|
|
8
|
-
const i18nContext = useContext(I18nContext)
|
|
9
|
-
|
|
10
|
-
return (
|
|
11
|
-
<WrappedComponent
|
|
12
|
-
{...props}
|
|
13
|
-
ref={ref}
|
|
14
|
-
t={i18nContext && i18nContext.t}
|
|
15
|
-
f={i18nContext && i18nContext.f}
|
|
16
|
-
lang={i18nContext && i18nContext.lang}
|
|
17
|
-
/>
|
|
18
|
-
)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
Wrapper.displayName = `withI18n(${
|
|
22
|
-
WrappedComponent.displayName || WrappedComponent.name
|
|
23
|
-
})`
|
|
24
|
-
|
|
25
|
-
return Wrapper
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default translate
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import Polyglot from 'node-polyglot'
|
|
2
|
-
|
|
3
|
-
import { DEFAULT_LANG } from '.'
|
|
4
|
-
|
|
5
|
-
export let _polyglot
|
|
6
|
-
|
|
7
|
-
export const initTranslation = (
|
|
8
|
-
lang,
|
|
9
|
-
dictRequire,
|
|
10
|
-
context,
|
|
11
|
-
defaultLang = DEFAULT_LANG
|
|
12
|
-
) => {
|
|
13
|
-
_polyglot = new Polyglot({
|
|
14
|
-
phrases: dictRequire(defaultLang),
|
|
15
|
-
locale: defaultLang
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
// Load global locales
|
|
19
|
-
if (lang && lang !== defaultLang) {
|
|
20
|
-
try {
|
|
21
|
-
const dict = dictRequire(lang)
|
|
22
|
-
_polyglot.extend(dict)
|
|
23
|
-
_polyglot.locale(lang)
|
|
24
|
-
} catch (e) {
|
|
25
|
-
console.warn(`The dict phrases for "${lang}" can't be loaded`)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Load context locales
|
|
30
|
-
if (context) {
|
|
31
|
-
try {
|
|
32
|
-
const dict = dictRequire(lang, context)
|
|
33
|
-
_polyglot.extend(dict)
|
|
34
|
-
} catch (e) {
|
|
35
|
-
console.warn(`The context ${context} cannot be loaded for lang ${lang}`)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return _polyglot
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const extend = (dict, polyglot) => (polyglot || _polyglot)?.extend(dict)
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import Polyglot from 'node-polyglot'
|
|
2
|
-
import { useState } from 'react'
|
|
3
|
-
|
|
4
|
-
import { useI18n } from '.'
|
|
5
|
-
import { extend } from './translation'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Hook to merge app locales with cozy-ui locales
|
|
9
|
-
* @param {object} locales - Locales sorted by lang `{ fr: {...}, en: {...} }`
|
|
10
|
-
* @returns {void}
|
|
11
|
-
*/
|
|
12
|
-
const useExtendI18n = locales => {
|
|
13
|
-
const { lang, polyglot } = useI18n()
|
|
14
|
-
// Use to determine if we need to merge locales again, and to avoid useless calls
|
|
15
|
-
const [useExtendI18nLang, setUseExtendI18nLang] = useState('')
|
|
16
|
-
|
|
17
|
-
if (!locales || !lang || !polyglot) return
|
|
18
|
-
|
|
19
|
-
// To simplify code we use Polyglot.extend to merge
|
|
20
|
-
// locales from object and from polyglot.phrases
|
|
21
|
-
// rather than native JS or lodash. this is why we have two extend.
|
|
22
|
-
if (useExtendI18nLang !== lang) {
|
|
23
|
-
const _polyglot = new Polyglot({
|
|
24
|
-
phrases: locales[lang],
|
|
25
|
-
locale: lang
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
// merge locales from app and cozy-ui, without replacing existing one in app
|
|
29
|
-
extend(polyglot.phrases, _polyglot)
|
|
30
|
-
// use merged locales in app
|
|
31
|
-
extend(_polyglot.phrases, polyglot)
|
|
32
|
-
// set the switch to avoid useless merge
|
|
33
|
-
setUseExtendI18nLang(lang)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export default useExtendI18n
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import omit from 'lodash/omit'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
|
|
4
|
-
import { I18n, translate } from '.'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
* @param {Function|Object} localesOrRequire - Either a function returning the locale for a lang,
|
|
9
|
-
* or an object containing all the locales
|
|
10
|
-
* @return {Component}
|
|
11
|
-
*/
|
|
12
|
-
const withLocales = localesOrRequire => Component => {
|
|
13
|
-
// The inner components needs to receive t
|
|
14
|
-
const Translated = translate()(Component)
|
|
15
|
-
|
|
16
|
-
const requireLocale =
|
|
17
|
-
typeof localesOrRequire === 'function'
|
|
18
|
-
? localesOrRequire
|
|
19
|
-
: localeCode => localesOrRequire[localeCode]
|
|
20
|
-
|
|
21
|
-
class Wrapped extends React.Component {
|
|
22
|
-
render() {
|
|
23
|
-
const { lang } = this.props
|
|
24
|
-
// Do not pass translate props downwards
|
|
25
|
-
// since the component is already augmented with translate()
|
|
26
|
-
const wrappedProps = omit(this.props, Object.keys(I18n.childContextTypes))
|
|
27
|
-
return (
|
|
28
|
-
<I18n dictRequire={requireLocale} lang={lang}>
|
|
29
|
-
<Translated {...wrappedProps} />
|
|
30
|
-
</I18n>
|
|
31
|
-
)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
Wrapped.propTypes = {
|
|
35
|
-
...(Component.propTypes || {}),
|
|
36
|
-
...I18n.childContextTypes
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
Wrapped.displayName = `withLocales(${
|
|
40
|
-
Component.displayName || Component.name
|
|
41
|
-
})`
|
|
42
|
-
|
|
43
|
-
// The outer component needs to receive lang
|
|
44
|
-
return translate()(Wrapped)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export default withLocales
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/react'
|
|
2
|
-
import React from 'react'
|
|
3
|
-
|
|
4
|
-
import { I18n } from '.'
|
|
5
|
-
import withLocales from './withLocales'
|
|
6
|
-
|
|
7
|
-
const globalLocales = {
|
|
8
|
-
en: {
|
|
9
|
-
'hello-world': 'Hello global world !'
|
|
10
|
-
},
|
|
11
|
-
fr: {
|
|
12
|
-
'hello-world': 'Bonjour le monde global !'
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const componentLocales = {
|
|
17
|
-
en: {
|
|
18
|
-
'hello-world': 'Hello local world !'
|
|
19
|
-
},
|
|
20
|
-
fr: {
|
|
21
|
-
'hello-world': 'Bonjour le monde local !'
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
class MockComponent extends React.Component {
|
|
26
|
-
render() {
|
|
27
|
-
const { t } = this.props
|
|
28
|
-
return <div>{t('hello-world')}</div>
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
describe('with locales', () => {
|
|
33
|
-
const setup = ({ lang, Component }) => {
|
|
34
|
-
render(
|
|
35
|
-
<I18n lang={lang} dictRequire={localeCode => globalLocales[localeCode]}>
|
|
36
|
-
<Component />
|
|
37
|
-
</I18n>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const testComponent = (Component, description) => {
|
|
42
|
-
describe(description, () => {
|
|
43
|
-
it('should provide t with correct locale strings', () => {
|
|
44
|
-
setup({ lang: 'en', Component })
|
|
45
|
-
expect(screen.getByText('Hello local world !')).toBeInTheDocument()
|
|
46
|
-
setup({ lang: 'fr', Component })
|
|
47
|
-
expect(screen.getByText('Bonjour le monde local !')).toBeInTheDocument()
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const TComponentObj = withLocales(componentLocales)(MockComponent)
|
|
53
|
-
const requireLang = lang => componentLocales[lang]
|
|
54
|
-
const TComponentFunc = withLocales(requireLang)(MockComponent)
|
|
55
|
-
|
|
56
|
-
testComponent(TComponentObj, 'locales from object')
|
|
57
|
-
testComponent(TComponentFunc, 'locales from require function')
|
|
58
|
-
})
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import React, { forwardRef } from 'react'
|
|
2
|
-
|
|
3
|
-
import { I18n, useI18n } from '.'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {Function|Object} localesOrRequire - Either a function returning the locale,
|
|
8
|
-
* or an object containing all the locales
|
|
9
|
-
* @return {Component}
|
|
10
|
-
*/
|
|
11
|
-
const withOnlyLocales = localesOrRequire => Component => {
|
|
12
|
-
const requireLocale =
|
|
13
|
-
typeof localesOrRequire === 'function'
|
|
14
|
-
? localesOrRequire
|
|
15
|
-
: localeCode => localesOrRequire[localeCode]
|
|
16
|
-
|
|
17
|
-
const Wrapped = forwardRef((props, ref) => {
|
|
18
|
-
const { lang } = useI18n()
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<I18n dictRequire={requireLocale} lang={lang}>
|
|
22
|
-
<Component {...props} ref={ref} />
|
|
23
|
-
</I18n>
|
|
24
|
-
)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
Wrapped.propTypes = {
|
|
28
|
-
...(Component.propTypes || {})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
Wrapped.displayName = `withOnlyLocales(${
|
|
32
|
-
Component.displayName || Component.name
|
|
33
|
-
})`
|
|
34
|
-
|
|
35
|
-
return Wrapped
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export default withOnlyLocales
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import createDepreciationLogger from "cozy-ui/transpiled/react/helpers/createDepreciationLogger";
|
|
3
|
-
import DeprecatedI18n, { useI18n as deprecatedUseI18n } from "cozy-ui/transpiled/react/providers/I18n";
|
|
4
|
-
var logDeprecatedFunc = createDepreciationLogger();
|
|
5
|
-
var logDeprecatedComp = createDepreciationLogger();
|
|
6
|
-
export var useI18n = function useI18n(props) {
|
|
7
|
-
logDeprecatedFunc("\"useI18n\" is now exported elsewhere. Please change the import path to \"cozy-ui/transpiled/react/providers/I18n\"");
|
|
8
|
-
return deprecatedUseI18n(props);
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
var I18n = function I18n(props) {
|
|
12
|
-
logDeprecatedComp("\"I18n\" is now exported elsewhere. Please change the import path to \"cozy-ui/transpiled/react/providers/I18n\"");
|
|
13
|
-
return /*#__PURE__*/React.createElement(DeprecatedI18n, props);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default I18n;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import createDepreciationLogger from "cozy-ui/transpiled/react/helpers/createDepreciationLogger";
|
|
2
|
-
import withLocales from "cozy-ui/transpiled/react/providers/I18n/withLocales";
|
|
3
|
-
var logDeprecatedWithLocale = createDepreciationLogger();
|
|
4
|
-
|
|
5
|
-
var deprecatedWithLocales = function deprecatedWithLocales(props) {
|
|
6
|
-
logDeprecatedWithLocale("\"withLocales\" is now exported elsewhere. Please change the import path to \"cozy-ui/transpiled/react/providers/I18n\"");
|
|
7
|
-
return withLocales(props);
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export default deprecatedWithLocales;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import Polyglot from 'node-polyglot';
|
|
2
|
-
import { useMemo } from 'react';
|
|
3
|
-
import { useI18n, DEFAULT_LANG } from "cozy-ui/transpiled/react/providers/I18n";
|
|
4
|
-
import { initFormat } from "cozy-ui/transpiled/react/providers/I18n/format";
|
|
5
|
-
|
|
6
|
-
var createUseI18n = function createUseI18n(locales) {
|
|
7
|
-
return function () {
|
|
8
|
-
var _ref = useI18n() || {
|
|
9
|
-
lang: DEFAULT_LANG
|
|
10
|
-
},
|
|
11
|
-
lang = _ref.lang;
|
|
12
|
-
|
|
13
|
-
return useMemo(function () {
|
|
14
|
-
var polyglot = new Polyglot({
|
|
15
|
-
locale: DEFAULT_LANG,
|
|
16
|
-
phrases: locales[DEFAULT_LANG]
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
if (lang && lang !== DEFAULT_LANG) {
|
|
20
|
-
try {
|
|
21
|
-
polyglot.locale(lang);
|
|
22
|
-
polyglot.extend(locales[lang]);
|
|
23
|
-
} catch (e) {
|
|
24
|
-
console.warn("The dict phrases for \"".concat(lang, "\" can't be loaded"));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var f = initFormat(lang);
|
|
29
|
-
var t = polyglot.t.bind(polyglot);
|
|
30
|
-
return {
|
|
31
|
-
t: t,
|
|
32
|
-
f: f,
|
|
33
|
-
lang: lang
|
|
34
|
-
};
|
|
35
|
-
}, [lang]);
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export default createUseI18n;
|