Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(locales): allow copying data from other locales (#5850) #5881

Merged
merged 1 commit into from
Nov 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import { css } from '@emotion/core';
import styled from '@emotion/styled';
import {
buttons,
colors,
Dropdown,
DropdownItem,
StyledDropdownButton,
buttons,
text,
} from 'netlify-cms-ui-default';

import EditorControl from './EditorControl';
import {
getI18nInfo,
isFieldTranslatable,
isFieldDuplicate,
isFieldHidden,
getLocaleDataPath,
hasI18n,
isFieldDuplicate,
isFieldHidden,
isFieldTranslatable,
} from '../../../lib/i18n';

const ControlPaneContainer = styled.div`
Expand All @@ -45,23 +45,24 @@ const LocaleButtonWrapper = styled.div`
display: flex;
`;

const LocaleRowWrapper = styled.div`
display: flex;
`;

const StyledDropdown = styled(Dropdown)`
width: max-content;
margin-top: 20px;
margin-bottom: 20px;
margin-right: 20px;
`;

function LocaleDropdown({ locales, selectedLocale, onLocaleChange, t }) {
function LocaleDropdown({ locales, dropdownText, onLocaleChange }) {
return (
<StyledDropdown
renderButton={() => {
return (
<LocaleButtonWrapper>
<LocaleButton>
{t('editor.editorControlPane.i18n.writingInLocale', {
locale: selectedLocale.toUpperCase(),
})}
</LocaleButton>
<LocaleButton>{dropdownText}</LocaleButton>
</LocaleButtonWrapper>
);
}}
Expand Down Expand Up @@ -113,6 +114,41 @@ export default class ControlPane extends React.Component {
this.props.onLocaleChange(val);
};

copyFromOtherLocale =
({ targetLocale, t }) =>
sourceLocale => {
if (
!window.confirm(
t('editor.editorControlPane.i18n.copyFromLocaleConfirm', {
locale: sourceLocale.toUpperCase(),
}),
)
) {
return;
}
const { entry, collection } = this.props;
const { locales, defaultLocale } = getI18nInfo(collection);

const locale = this.state.selectedLocale;
const i18n = locales && {
currentLocale: locale,
locales,
defaultLocale,
};

this.props.fields.forEach(field => {
if (isFieldTranslatable(field, targetLocale, sourceLocale)) {
const copyValue = getFieldValue({
field,
entry,
locale: sourceLocale,
isTranslatable: sourceLocale !== defaultLocale,
});
this.props.onChange(field, copyValue, undefined, i18n);
}
});
};

validate = async () => {
this.props.fields.forEach(field => {
if (field.get('widget') === 'hidden') return;
Expand All @@ -130,8 +166,8 @@ export default class ControlPane extends React.Component {
};

render() {
const { collection, entry, fieldsMetaData, fieldsErrors, onChange, onValidate, t } = this.props;
const fields = this.props.fields;
const { collection, entry, fields, fieldsMetaData, fieldsErrors, onChange, onValidate, t } =
this.props;

if (!collection || !fields) {
return null;
Expand All @@ -152,12 +188,20 @@ export default class ControlPane extends React.Component {
return (
<ControlPaneContainer>
{locales && (
<LocaleDropdown
locales={locales}
selectedLocale={locale}
onLocaleChange={this.handleLocaleChange}
t={t}
/>
<LocaleRowWrapper>
<LocaleDropdown
locales={locales}
dropdownText={t('editor.editorControlPane.i18n.writingInLocale', {
locale: locale.toUpperCase(),
})}
onLocaleChange={this.handleLocaleChange}
/>
<LocaleDropdown
locales={locales.filter(l => l !== locale)}
dropdownText={t('editor.editorControlPane.i18n.copyFromLocale')}
onLocaleChange={this.copyFromOtherLocale({ targetLocale: locale, t })}
/>
</LocaleRowWrapper>
)}
{fields
.filter(f => f.get('widget') !== 'hidden')
Expand All @@ -179,9 +223,10 @@ export default class ControlPane extends React.Component {
})}
fieldsMetaData={fieldsMetaData}
fieldsErrors={fieldsErrors}
onChange={(field, newValue, newMetadata) =>
onChange(field, newValue, newMetadata, i18n)
}
onChange={(field, newValue, newMetadata) => {
console.log('newMeta', newMetadata);
onChange(field, newValue, newMetadata, i18n);
}}
onValidate={onValidate}
processControlRef={this.controlRef.bind(this)}
controlRef={this.controlRef}
Expand Down
3 changes: 3 additions & 0 deletions packages/netlify-cms-locales/src/de/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ const de = {
},
i18n: {
writingInLocale: 'Aktuelle Sprache: %{locale}',
copyFromLocale: 'Aus anderer Sprache übernehmen',
copyFromLocaleConfirm:
'Wollen Sie wirklich die Daten aus der Sprache %{locale} übernehmen?\nAlle bishergen Inhalte werden überschrieben.',
},
},
editor: {
Expand Down
3 changes: 3 additions & 0 deletions packages/netlify-cms-locales/src/en/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ const en = {
},
i18n: {
writingInLocale: 'Writing in %{locale}',
copyFromLocale: 'Fill in from another locale',
copyFromLocaleConfirm:
'Do you want to fill in data from %{locale} locale?\nAll existing content will be overwritten.',
},
},
editor: {
Expand Down