Skip to content

Commit

Permalink
Re-design translations according to i18n rules
Browse files Browse the repository at this point in the history
Replace all usages of tKey (translation key) with function toLabel(t).
Motivation:
1. linter expects translations as literals (i.e. t('Foo')). Warnings
   are reported when translation key is provided as a variable.
2. auto-generation of translation file requires literals in source or
   in comments

Signed-off-by: Radoslaw Szwajkowski <[email protected]>
  • Loading branch information
rszwajko committed Oct 4, 2022
1 parent 8ad696b commit 94260d4
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 113 deletions.
61 changes: 29 additions & 32 deletions locales/en/plugin__forklift-console-plugin.json
Original file line number Diff line number Diff line change
@@ -1,52 +1,49 @@
{
"AddProvider": "Add Provider",
"Any": "Any",
"{{type}} provider {{name}} will no longer be selectable as a migration source.": "{{type}} provider {{name}} will no longer be selectable as a migration source.",
"{{type}} provider {{name}} will no longer be selectable as a migration target.": "{{type}} provider {{name}} will no longer be selectable as a migration target.",
"Add Provider": "Add Provider",
"Cancel": "Cancel",
"CannotDeleteProvider": "Cannot remove provider",
"ClearAllFilters": "Clear all filters",
"Cannot remove provider": "Cannot remove provider",
"Clear all filters": "Clear all filters",
"Clusters": "Clusters",
"Delete": "Delete",
"DeleteProvider": "Delete Provider",
"EditProvider": "Edit Provider",
"Delete Provider": "Delete Provider",
"Edit Provider": "Edit Provider",
"Endpoint": "Endpoint",
"False": "False",
"FilterByName": "Filter by name",
"FilterByNamespace": "Filter by namespace",
"FilterByStatus": "Filter by status",
"FilterByType": "Filter by type",
"FilterByUrl": "Filter by endpoint",
"Filter by endpoint": "Filter by endpoint",
"Filter by name": "Filter by name",
"Filter by namespace": "Filter by namespace",
"Hosts": "Hosts",
"Loading": "Loading...",
"ManageColumns": "Manage columns",
"KubeVirt": "KubeVirt",
"Loading": "Loading",
"Manage Columns": "Manage Columns",
"Mappings for VM Import": "Mappings for VM Import",
"Name": "Name",
"Namespace": "Namespace",
"Networks": "Networks",
"NoResultsFound": "No results found",
"NoResultsMatchFilter": "No results match the filter criteria. Clear all filters and try again.",
"Openshift": "Openshift",
"Ovirt": "oVirt",
"PermanentlyDeleteProvider": "Permanently delete provider?",
"No information": "No information",
"No results found": "No results found",
"No results match the filter criteria. Clear all filters and try again.": "No results match the filter criteria. Clear all filters and try again.",
"oVirt": "oVirt",
"Permanently delete provider?": "Permanently delete provider?",
"Plans for VM Import": "Plans for VM Import",
"ProviderNoLongerSelectableAsSource": "{{type}} provider {{name}} will no longer be selectable as a migration source.",
"ProviderNoLongerSelectableAsTarget": "{{type}} provider {{name}} will no longer be selectable as a migration target.",
"Providers": "Providers",
"Providers for VM Import": "Providers for VM Import",
"Ready": "Ready",
"Reorder": "Reorder",
"RestoreDefaultColums": "Restore default colums",
"Restore default colums": "Restore default colums",
"Save": "Save",
"SelectFilter": "Select Filter",
"SelectMigrationNetwork": "Select migration network",
"Status": "Status",
"Select Filter": "Select Filter",
"Select migration network": "Select migration network",
"Selected columns will be displayed in the table.": "Selected columns will be displayed in the table.",
"Storage": "Storage",
"Success": "Success",
"TableColumnManagement": "Table column management",
"Type": "Type",
"Table column management": "Table column management",
"True": "True",
"UnableToRetrieve": "Unable to retrieve data",
"Type": "Type",
"Unable to retrieve data": "Unable to retrieve data",
"Unknown": "Unknown",
"Url": "Endpoint",
"Virtualization": "Virtualization",
"Vsphere": "vSphere",
"VMs": "VMs"
}
"VMs": "VMs",
"VMware": "VMware"
}
45 changes: 31 additions & 14 deletions src/Providers/ProviderRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const StatusCell = ({ value, entity: { conditions } }: CellProps) => {
const existingConditions = Object.values(conditions).filter(Boolean);
const toState = (value) =>
value === 'True' ? 'Ok' : value === 'False' ? 'Error' : 'Unknown';
const label =
value === 'True'
? t('True')
: value === 'False'
? t('False')
: t('Unknown');
return (
<Popover
hasAutoWidth
Expand All @@ -43,12 +49,12 @@ const StatusCell = ({ value, entity: { conditions } }: CellProps) => {
/>
);
})
: 'No information'}
: t('No information')}
</div>
}
>
<Button variant="link" isInline aria-label={t(value)}>
<StatusIcon status={toState(value)} label={t(value)} />
<Button variant="link" isInline aria-label={label}>
<StatusIcon status={toState(value)} label={label} />
</Button>
</Popover>
);
Expand All @@ -74,7 +80,7 @@ const ProviderRow = ({ columns, entity }: RowProps<MergedProvider>) => {
const { t } = useTranslation();
const [isActionMenuOpen, setIsActionMenuOpen] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
console.warn('Modal open?', isDeleteModalOpen, entity);

const toggleDeleteModal = () => setIsDeleteModalOpen(!isDeleteModalOpen);
const deleteProviderMutation = useDeleteProviderMutation(
entity.type as ProviderType,
Expand Down Expand Up @@ -102,13 +108,13 @@ const ProviderRow = ({ columns, entity }: RowProps<MergedProvider>) => {
isPlain
dropdownItems={[
<DropdownItem key="edit" onClick={editProvider}>
{t('EditProvider')}
{t('Edit Provider')}
</DropdownItem>,
<DropdownItem key="delete" onClick={toggleDeleteModal}>
{t('DeleteProvider')}
{t('Delete Provider')}
</DropdownItem>,
<DropdownItem key="selectNetwork" onClick={selectNetwork}>
{t('SelectMigrationNetwork')}
{t('Select migration network')}
</DropdownItem>,
]}
/>
Expand All @@ -130,15 +136,26 @@ const ProviderRow = ({ columns, entity }: RowProps<MergedProvider>) => {
})
}
mutateResult={deleteProviderMutation}
title={t('PermanentlyDeleteProvider')}
body={t(
title={t('Permanently delete provider?')}
body={
isTarget(entity.type as ProviderType)
? 'ProviderNoLongerSelectableAsTarget'
: 'ProviderNoLongerSelectableAsSource',
{ type: entity.type, name: entity.name },
)}
? t(
'{{type}} provider {{name}} will no longer be selectable as a migration target.',
{
type: entity.type,
name: entity.name,
},
)
: t(
'{{type}} provider {{name}} will no longer be selectable as a migration source.',
{
type: entity.type,
name: entity.name,
},
)
}
confirmButtonText={t('Delete')}
errorText={t('CannotDeleteProvider')}
errorText={t('Cannot remove provider')}
cancelButtonText={t('Cancel')}
/>
</Td>
Expand Down
63 changes: 35 additions & 28 deletions src/Providers/ProvidersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,95 +47,98 @@ import ProviderRow from './ProviderRow';
const fieldsMetadata: Field[] = [
{
id: NAME,
tKey: 'Name',
toLabel: (t) => t('Name'),
isVisible: true,
isIdentity: true,
filter: {
type: 'freetext',
placeholderKey: 'FilterByName',
toPlaceholderLabel: (t) => t('Filter by name'),
},
sortable: true,
},
{
id: NAMESPACE,
tKey: 'Namespace',
toLabel: (t) => t('Namespace'),
isVisible: true,
isIdentity: true,
filter: {
type: 'freetext',
placeholderKey: 'FilterByNamespace',
toPlaceholderLabel: (t) => t('Filter by namespace'),
},
sortable: true,
},
{
id: READY,
tKey: 'Ready',
toLabel: (t) => t('Ready'),
isVisible: true,
filter: {
type: 'enum',
primary: true,
placeholderKey: 'Ready',
toPlaceholderLabel: (t) => t('Ready'),
values: [
{ id: 'True', tKey: 'True' },
{ id: 'False', tKey: 'False' },
{ id: 'Unknown', tKey: 'Unknown' },
{ id: 'True', toLabel: (t) => t('True') },
{ id: 'False', toLabel: (t) => t('False') },
{ id: 'Unknown', toLabel: (t) => t('Unknown') },
],
},
sortable: true,
},
{
id: URL,
tKey: 'Url',
toLabel: (t) => t('Endpoint'),
isVisible: true,
filter: {
type: 'freetext',
placeholderKey: 'FilterByUrl',
toPlaceholderLabel: (t) => t('Filter by endpoint'),
},
sortable: true,
},
{
id: TYPE,
tKey: 'Type',
toLabel: (t) => t('Type'),
isVisible: true,
filter: {
type: 'enum',
primary: true,
placeholderKey: 'Type',
toPlaceholderLabel: (t) => t('Type'),
values: [
{ id: 'vsphere', tKey: 'Vsphere' },
{ id: 'ovirt', tKey: 'Ovirt' },
{ id: 'openshift', tKey: 'Openshift' },
// t('VMware')
{ id: 'vsphere', toLabel: (t) => t('VMware') },
// t('oVirt')
{ id: 'ovirt', toLabel: (t) => t('oVirt') },
// t('KubeVirt')
{ id: 'openshift', toLabel: (t) => t('KubeVirt') },
],
},
sortable: true,
},
{
id: VM_COUNT,
tKey: 'VMs',
toLabel: (t) => t('VMs'),
isVisible: true,
sortable: true,
},
{
id: NETWORK_COUNT,
tKey: 'Networks',
toLabel: (t) => t('Networks'),
isVisible: true,
sortable: true,
},
{
id: CLUSTER_COUNT,
tKey: 'Clusters',
toLabel: (t) => t('Clusters'),
isVisible: true,
sortable: true,
},
{
id: HOST_COUNT,
tKey: 'Hosts',
toLabel: (t) => t('Hosts'),
isVisible: false,
sortable: true,
},
{
id: STORAGE_COUNT,
tKey: 'Storage',
toLabel: (t) => t('Storage'),
isVisible: false,
sortable: true,
},
Expand Down Expand Up @@ -180,15 +183,15 @@ export const ProvidersPage = ({ namespace, kind }: ProvidersPageProps) => {
</LevelItem>
<LevelItem>
<Button variant="primary" onClick={() => ''}>
{t('AddProvider')}
{t('Add Provider')}
</Button>
</LevelItem>
</Level>
</PageSection>
<PageSection>
<Toolbar
clearAllFilters={clearAllFilters}
clearFiltersButtonText={t('ClearAllFilters')}
clearFiltersButtonText={t('Clear all filters')}
>
<ToolbarContent>
<ToolbarToggleGroup toggleIcon={<FilterIcon />} breakpoint="xl">
Expand Down Expand Up @@ -245,7 +248,7 @@ const ErrorState = () => {
<EmptyState>
<EmptyStateIcon icon={RedExclamationCircleIcon} />
<Title headingLevel="h4" size="lg">
{t('UnableToRetrieve')}
{t('Unable to retrieve data')}
</Title>
</EmptyState>
);
Expand All @@ -269,7 +272,7 @@ const NoResultsFound = () => {
<EmptyState>
<EmptyStateIcon icon={SearchIcon} />
<Title size="lg" headingLevel="h4">
{t('NoResultsFound')}
{t('No results found')}
</Title>
</EmptyState>
);
Expand All @@ -285,12 +288,16 @@ const NoResultsMatchFilter = ({
<EmptyState>
<EmptyStateIcon icon={SearchIcon} />
<Title size="lg" headingLevel="h4">
{t('NoResultsFound')}
{t('No results found')}
</Title>
<EmptyStateBody>{t('NoResultsMatchFilter')}</EmptyStateBody>
<EmptyStateBody>
{t(
'No results match the filter criteria. Clear all filters and try again.',
)}
</EmptyStateBody>
<EmptyStatePrimary>
<Button variant="link" onClick={clearAllFilters}>
{t('ClearAllFilters')}
{t('Clear all filters')}
</Button>
</EmptyStatePrimary>
</EmptyState>
Expand Down
14 changes: 7 additions & 7 deletions src/components/Filter/AttributeValueFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,19 @@ export const AttributeValueFilter = ({
onToggle={setExpanded}
isOpen={expanded}
variant={SelectVariant.single}
aria-label={t('SelectFilter')}
aria-label={t('Select Filter')}
selections={toSelectOption(
currentFilterType.id,
t(currentFilterType.tKey),
currentFilterType.toLabel(t),
)}
>
{filterTypes.map(({ id, tKey }) => (
<SelectOption key={id} value={toSelectOption(id, t(tKey))} />
{filterTypes.map(({ id, toLabel }) => (
<SelectOption key={id} value={toSelectOption(id, toLabel(t))} />
))}
</Select>
</ToolbarItem>

{filterTypes.map(({ id, tKey: fieldKey, filter }) => {
{filterTypes.map(({ id, toLabel: toFieldLabel, filter }) => {
const FieldFilter = supportedFilters[filter.type];
return (
FieldFilter && (
Expand All @@ -74,10 +74,10 @@ export const AttributeValueFilter = ({
[id]: values,
})
}
placeholderLabel={t(filter.placeholderKey)}
placeholderLabel={filter.toPlaceholderLabel(t)}
selectedFilters={selectedFilters[id] ?? []}
showFilter={currentFilterType?.id === id}
title={t(filter.tKey ?? fieldKey)}
title={filter?.toLabel?.(t) ?? toFieldLabel(t)}
supportedValues={filter.values}
/>
)
Expand Down
Loading

0 comments on commit 94260d4

Please sign in to comment.