diff --git a/CHANGELOG.md b/CHANGELOG.md index 24f3e01cb0f..b17ad542c08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -No public interface changes since `6.7.4`. +- Converted a number of components to support text localization ([#1485](https://github.com/elastic/eui/pull/1485)) ## [`6.7.4`](https://github.com/elastic/eui/tree/v6.7.4) diff --git a/package.json b/package.json index 11402d7a504..66945f518d5 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "react-ace": "^5.5.0", "react-color": "^2.13.8", "react-input-autosize": "^2.2.1", + "react-is": "~16.3.0", "react-virtualized": "^9.18.5", "react-vis": "1.10.2", "resize-observer-polyfill": "^1.5.0", @@ -76,6 +77,7 @@ "@types/enzyme": "^3.1.13", "@types/jest": "^23.3.9", "@types/react": "^16.3.0", + "@types/react-is": "~16.3.0", "@types/react-virtualized": "^9.18.6", "@types/uuid": "^3.4.4", "autoprefixer": "^7.1.5", diff --git a/src/components/bottom_bar/bottom_bar.js b/src/components/bottom_bar/bottom_bar.js index 15dbd24c382..7e4122fe1d7 100644 --- a/src/components/bottom_bar/bottom_bar.js +++ b/src/components/bottom_bar/bottom_bar.js @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { EuiPortal } from '../portal'; import { EuiScreenReaderOnly } from '../accessibility'; +import { EuiI18n } from '../i18n'; const paddingSizeToClassNameMap = { none: null, @@ -53,7 +54,10 @@ export class EuiBottomBar extends Component {

- There is a new menu opening with page level controls at the bottom of the document. +

+ + {([fullscreenCollapse, fullscreenExpand]) => ( + + )} + ); } diff --git a/src/components/code_editor/__snapshots__/code_editor.test.js.snap b/src/components/code_editor/__snapshots__/code_editor.test.js.snap index c1b4ef1b279..a3b2b19c116 100644 --- a/src/components/code_editor/__snapshots__/code_editor.test.js.snap +++ b/src/components/code_editor/__snapshots__/code_editor.test.js.snap @@ -11,16 +11,12 @@ exports[`EuiCodeEditor behavior hint element should be disabled when the ui ace

- Press Enter to start - editing - . + Press Enter to start editing.

- When you’re done, press Escape to stop - editing - . + When you're done, press Escape to stop editing.

`; @@ -36,16 +32,12 @@ exports[`EuiCodeEditor behavior hint element should be enabled when the ui ace b

- Press Enter to start - editing - . + Press Enter to start editing.

- When you’re done, press Escape to stop - editing - . + When you're done, press Escape to stop editing.

`; @@ -61,16 +53,12 @@ exports[`EuiCodeEditor behavior hint element should be tabable 1`] = `

- Press Enter to start - editing - . + Press Enter to start editing.

- When you’re done, press Escape to stop - editing - . + When you're done, press Escape to stop editing.

`; @@ -95,7 +83,7 @@ exports[`EuiCodeEditor is rendered 1`] = `

- When you’re done, press Escape to stop editing. + When you're done, press Escape to stop editing.

- When you’re done, press Escape to stop editing. + When you're done, press Escape to stop editing.

- When you’re done, press Escape to stop editing. + When you're done, press Escape to stop editing.

- When you’re done, press Escape to stop interacting with the code. + When you're done, press Escape to stop interacting with the code.

- Press Enter to start {activity}. + { + isReadOnly + ? ( + + ) + : ( + + ) + }

- When you’re done, press Escape to stop {activity}. + { + isReadOnly + ? ( + + ) + : ( + + ) + }

); diff --git a/src/components/color_picker/color_picker.js b/src/components/color_picker/color_picker.js index 0a93aacd53d..a78d5e4b397 100644 --- a/src/components/color_picker/color_picker.js +++ b/src/components/color_picker/color_picker.js @@ -8,6 +8,7 @@ import { ChromePicker } from 'react-color'; import { EuiOutsideClickDetector } from '../outside_click_detector'; import { EuiColorPickerSwatch } from './color_picker_swatch'; +import { EuiI18n } from '../i18n'; export class EuiColorPicker extends Component { constructor(props) { @@ -30,15 +31,32 @@ export class EuiColorPicker extends Component { }; getColorLabel() { - const { color } = this.props; - const colorValue = color === null ? '(transparent)' : color; return ( -
- { colorValue } -
+ {transparentColor => { + const { color } = this.props; + const colorValue = color === null ? `(${transparentColor})` : color; + return ( + + {colorSelectionLabel => ( +
+ { colorValue } +
+ )} +
+ ); + }} + ); } diff --git a/src/components/combo_box/combo_box_input/combo_box_pill.js b/src/components/combo_box/combo_box_input/combo_box_pill.js index 0b61b078bcd..956ad43e297 100644 --- a/src/components/combo_box/combo_box_input/combo_box_pill.js +++ b/src/components/combo_box/combo_box_input/combo_box_pill.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiBadge } from '../../badge'; +import { EuiI18n } from '../../i18n'; export class EuiComboBoxPill extends Component { static propTypes = { @@ -47,23 +48,31 @@ export class EuiComboBoxPill extends Component { if (onClose) { return ( - - {children} - + {removeSelection => ( + + {children} + + )} + ); } diff --git a/src/components/combo_box/combo_box_options_list/combo_box_options_list.js b/src/components/combo_box/combo_box_options_list/combo_box_options_list.js index c8838ae0355..a85242f801f 100644 --- a/src/components/combo_box/combo_box_options_list/combo_box_options_list.js +++ b/src/components/combo_box/combo_box_options_list/combo_box_options_list.js @@ -11,6 +11,7 @@ import { EuiText } from '../../text'; import { EuiLoadingSpinner } from '../../loading'; import { EuiComboBoxOption } from './combo_box_option'; import { EuiComboBoxTitle } from './combo_box_title'; +import { EuiI18n } from '../../i18n'; const positionToClassNameMap = { top: 'euiComboBoxOptionsList--top', @@ -129,7 +130,7 @@ export class EuiComboBoxOptionsList extends Component { - Loading options + ); @@ -139,22 +140,48 @@ export class EuiComboBoxOptionsList extends Component { if (selectedOptionForValue) { // Disallow duplicate custom options. emptyStateContent = ( -

{selectedOptionForValue.value} has already been added

+

+ {selectedOptionForValue.label} }} + /> +

); } else { emptyStateContent = ( -

Hit ENTER to add {searchValue} as a custom option

+

+ ENTER, searchValue: {searchValue} }} + /> +

); } } else { emptyStateContent = ( -

{searchValue} doesn’t match any options

+

+ {searchValue} }} + /> +

); } } else if (!options.length) { - emptyStateContent =

There aren’t any options available

; + emptyStateContent = ( +

+ +

+ ); } else if (areAllOptionsSelected) { - emptyStateContent =

You’ve selected all available options

; + emptyStateContent = ( +

+ +

+ ); } const emptyState = emptyStateContent ? ( diff --git a/src/components/context/context.tsx b/src/components/context/context.tsx index be1fb75aa3e..7f610ec3421 100644 --- a/src/components/context/context.tsx +++ b/src/components/context/context.tsx @@ -1,8 +1,14 @@ import React, { createContext, ReactChild } from 'react'; +export interface RenderableValues { + [key: string]: ReactChild; +} + +export type Renderable = ReactChild | ((values: T) => ReactChild); + export interface I18nShape { mapping?: { - [key: string]: ReactChild; + [key: string]: Renderable; }; formatNumber?: (x: number) => string; formatDateTime?: (x: Date) => string; diff --git a/src/components/form/file_picker/file_picker.js b/src/components/form/file_picker/file_picker.js index 50c3f2f45df..93d2d208723 100644 --- a/src/components/form/file_picker/file_picker.js +++ b/src/components/form/file_picker/file_picker.js @@ -6,6 +6,7 @@ import classNames from 'classnames'; import { EuiButtonEmpty } from '../../button'; import { EuiIcon } from '../../icon'; +import { EuiI18n } from '../../i18n'; export class EuiFilePicker extends Component { static propTypes = { @@ -39,9 +40,9 @@ export class EuiFilePicker extends Component { }; } - handleChange = () => { + handleChange = (filesSelected) => { if (this.fileInput.files && this.fileInput.files.length > 1) { - this.setState({ promptText: `${this.fileInput.files.length} files selected` }); + this.setState({ promptText: `${this.fileInput.files.length} ${filesSelected}` }); } else if (this.fileInput.files.length === 0) { this.setState({ promptText: this.props.initialPromptText }); } else { @@ -73,92 +74,101 @@ export class EuiFilePicker extends Component { }; render() { - const { - id, - name, - initialPromptText, - className, - disabled, - compressed, - onChange, // eslint-disable-line no-unused-vars - ...rest - } = this.props; + return ( + + {([clearSelectedFiles, filesSelected]) => { + const { + id, + name, + initialPromptText, + className, + disabled, + compressed, + onChange, // eslint-disable-line no-unused-vars + ...rest + } = this.props; - const classes = classNames( - 'euiFilePicker', - { - 'euiFilePicker__showDrop': this.state.isHoveringDrop, - 'euiFilePicker--compressed': compressed, - 'euiFilePicker-hasFiles': this.state.promptText !== initialPromptText, - }, - className - ); + const classes = classNames( + 'euiFilePicker', + { + 'euiFilePicker__showDrop': this.state.isHoveringDrop, + 'euiFilePicker--compressed': compressed, + 'euiFilePicker-hasFiles': this.state.promptText !== initialPromptText, + }, + className + ); - let clearButton; - if (this.state.promptText !== initialPromptText) { - if (compressed) { - clearButton = ( - - ); - } else { - clearButton = ( - - Remove - - ); - } - } else { - clearButton = null; - } + let clearButton; + if (this.state.promptText !== initialPromptText) { + if (compressed) { + clearButton = ( + + ); + } else { + clearButton = ( + + Remove + + ); + } + } else { + clearButton = null; + } - return ( -
-
- { this.fileInput = input; }} - onDragOver={this.showDrop} - onDragLeave={this.hideDrop} - onDrop={this.hideDrop} - disabled={disabled} - {...rest} - /> -
-
-
-
+ ); + }} +
); } } diff --git a/src/components/form/form.js b/src/components/form/form.js index 0af76cc4d7b..033a1b627cf 100644 --- a/src/components/form/form.js +++ b/src/components/form/form.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiCallOut } from '../call_out'; +import { EuiI18n } from '../i18n'; export const EuiForm = ({ children, @@ -31,13 +32,17 @@ export const EuiForm = ({ if (isInvalid) { optionalErrorAlert = ( - - {optionalErrors} - + + {addressFormErrors => ( + + {optionalErrors} + + )} + ); } diff --git a/src/components/form/form_control_layout/form_control_layout_clear_button.js b/src/components/form/form_control_layout/form_control_layout_clear_button.js index 14dc0519181..94ead09c8f9 100644 --- a/src/components/form/form_control_layout/form_control_layout_clear_button.js +++ b/src/components/form/form_control_layout/form_control_layout_clear_button.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames'; import { EuiIcon } from '../../icon'; +import { EuiI18n } from '../../i18n'; export const EuiFormControlLayoutClearButton = ({ className, @@ -12,17 +13,21 @@ export const EuiFormControlLayoutClearButton = ({ const classes = classNames('euiFormControlLayoutClearButton', className); return ( - + + {label => ( + + )} + ); }; diff --git a/src/components/form/super_select/__snapshots__/super_select.test.js.snap b/src/components/form/super_select/__snapshots__/super_select.test.js.snap index 99d8bfd21ae..97ad52e0b57 100644 --- a/src/components/form/super_select/__snapshots__/super_select.test.js.snap +++ b/src/components/form/super_select/__snapshots__/super_select.test.js.snap @@ -144,7 +144,8 @@ exports[`EuiSuperSelect props custom display is propagated to dropdown 1`] = ` class="euiScreenReaderOnly" role="alert" > - You are in a form selector of 2 items and must select a single option. Use the up and down keys to navigate or escape to close. + You are in a form selector of 2 items and must select a single option. + Use the up and down keys to navigate or escape to close.

- You are in a form selector of 2 items and must select a single option. Use the up and down keys to navigate or escape to close. + You are in a form selector of 2 items and must select a single option. + Use the up and down keys to navigate or escape to close.

- Select an option: - Option #1 - , is selected + + Select an option: Option #1, is selected +