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
Add i18n to topology package #7315
Add i18n to topology package #7315
Conversation
/retest |
<strong>{node.getLabel()}</strong> | ||
{targetGroup | ||
? t('topology~ from {{sourceGroup}} to {{targetGroup}}?', { | ||
sourceGroup: sourceGroup.getLabel(), | ||
targetGroup: targetGroup.getLabel(), | ||
}) | ||
: t('topology~ from {{sourceGroup}}?', { sourceGroup: sourceGroup.getLabel() })} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 There is a pattern that can be used here...
Quick search through the codebase got me:
"teams-help": "Optionally list organizations. If specified, only GitHub users that are members of at least one of the listed organizations will be allowed to log in. Cannot be used in combination with <1>teams</1>.",
And:
<Trans i18nKey="teams-help" ns="github-idp-form">
Optionally list organizations. If specified, only GitHub users that are members of at
least one of the listed organizations will be allowed to log in. Cannot be used in
combination with <strong>teams</strong>.
</Trans>
Ref: github-idp-form.tsx
cc @christianvogt might know more -- I'm reverse engineering here.
@@ -29,15 +30,15 @@ const cleanUpWorkloadNode = async (workload: OdcNodeModel): Promise<K8sResourceK | |||
return cleanUpWorkload(workload.resource, workload.data?.isKnativeResource ?? false); | |||
}; | |||
|
|||
const deleteGroup = (application: TopologyApplicationObject) => { | |||
const deleteGroup = (application: TopologyApplicationObject, t: TFunction) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, you put t
at the start of other methods 🤔
I have no opinion one way or another, just thought it was noteworthy.
{t('topology~Connect')} | ||
<strong>{` ${edge.getSource().getLabel()} `}</strong> | ||
to | ||
{t('topology~to')} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be one translation otherwise it won't come out properly in other languages.
|
||
const ConnectedTopologyServiceBindingRequestPanel: React.FC<PropsFromState & | ||
PropsFromDispatch & | ||
TopologyServiceBindingRequestPanelProps> = ({ edge, onClickTab, selectedDetailsTab }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand what is happening here... why this change? Seems like new functionality for an I18n PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I question the use of passing around t
over simply using the global translation function when the translation of errors isn't reactive anyways.
|
||
namespace ExtensionProperties { | ||
export interface PostFormSubmissionAction<T, P> { | ||
/** action type */ | ||
type: string; | ||
/** callback for the related action */ | ||
callback: (arg: T, payload?: P) => Promise<T>; | ||
callback: (t: TFunction, arg: T, payload?: P) => Promise<T>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't necessary. It seems like the only reason for translation is related to error messages.
These error messages can be translated using the global i18next
object because there's no way these will be reactive anyways to a change in locale. We wouldn't be running the callback again with the new lang so therefore it's a one time translation.
const resourceObj = getResource(edge.getSource()); | ||
const resourceModel = modelFor(referenceFor(resourceObj)); | ||
|
||
return { | ||
label: 'Move Connector', | ||
label: t('topology~Move Connector'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use labelKey
for actions.
callback: () => { | ||
moveConnectionModal({ edge, availableTargets }); | ||
moveConnectionModal({ edge, availableTargets, t: (x) => x }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary to pass t
here because the modal has access to useTranslation
or withTranslation
.
@@ -15,33 +16,33 @@ import { TYPE_CONNECTS_TO, TYPE_SERVICE_BINDING, TYPE_TRAFFIC_CONNECTOR } from ' | |||
import { moveConnectionModal } from '../components/modals/MoveConnectionModal'; | |||
import { removeConnection } from '../utils'; | |||
|
|||
const moveConnection = (edge: Edge, availableTargets: Node[]) => { | |||
const moveConnection = (edge: Edge, availableTargets: Node[], t: TFunction) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should use labelKey for actions.
Same comment for all actions.
submitDanger: true, | ||
executeFn: () => { | ||
return removeTopologyResourceConnection(edge).catch((err) => { | ||
return removeTopologyResourceConnection(t, edge).catch((err) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to have confirmModal
accept a callback which is either executed in the render context so that the function can use useTranslation
or it gets passed in the translation function. This would make it easier to use these modal launchers without the need for the consumer to provide it's own t
function.
@@ -97,6 +98,7 @@ export const getResourceKind = (node: Node): K8sResourceKindReference => { | |||
}; | |||
|
|||
export const updateTopologyResourceApplication = ( | |||
t: TFunction, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again it seems we're passing around t
to localize the return value of async operations that won't be re-run if the locale changes.
Seems unnecessary to pass t
around everywhere for this and instead use the global i18next
aria-label="Shortcuts" | ||
bodyContent={TopologyShortcuts} | ||
aria-label={t('topology~Shortcuts')} | ||
bodyContent={getTopologyShortcuts(t)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API accepts a ReactNode
. TopologyShortcuts
can make use of useTranslation
bodyContent={getTopologyShortcuts(t)} | |
bodyContent={<TopologyShortcuts />} |
@@ -42,6 +45,7 @@ const MoveConnectionForm: React.FC<FormikProps<FormikValues> & MoveConnectionMod | |||
isSubmitting, | |||
cancel, | |||
values, | |||
t, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use useTranslation
instead.
@@ -31,6 +34,7 @@ type EditApplicationModalProps = EditApplicationFormProps & { | |||
}; | |||
|
|||
const EditApplicationForm: React.FC<FormikProps<FormikValues> & EditApplicationFormProps> = ({ | |||
t, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use useTranslation
instead.
@@ -75,7 +76,7 @@ export const groupContextMenu = (element: Node, connectorSource?: Node) => { | |||
|
|||
const graphData = element.getGraph().getData(); | |||
return createMenuItems( | |||
kebabOptionsToMenu(groupActions(graphData, applicationData, connectorSource)), | |||
kebabOptionsToMenu(groupActions(t, graphData, applicationData, connectorSource)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actions can use labelKey
dd486e1
to
ef896bb
Compare
@andrewballantyne Side bar is part of public/components/overview (not topology). I believe I have addressed other comments. |
ef896bb
to
4373009
Compare
/retest |
<<<<<<< HEAD | ||
const { filters, setTopologyFilters: onFiltersChange } = React.useContext(FilterContext); | ||
======= | ||
const { t } = useTranslation(); | ||
>>>>>>> Add i18n to topology package |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeff-phillips-18 Missed this Merge conflict marker encountered.
4373009
to
6f69e98
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I misunderstand Trans
vs t
... but I think you can use t
for all strings, and Trans
when React components or DOM elements get in the way
Search results may appear outside of the visible area.{' '} | ||
<Trans ns="topology"> | ||
Search results may appear outside of the visible area. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we still need the space 🤔
const title = targetGroup ? ( | ||
<Trans ns="topology">Move Component Node</Trans> | ||
) : ( | ||
<Trans ns="topology">Remove Component Node from Application</Trans> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think you need to use Trans
on static strings 🤔
const btnText = targetGroup ? ( | ||
<Trans ns="topology">Move</Trans> | ||
) : ( | ||
<Trans ns="topology">Remove</Trans> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
<Trans ns="topology"> | ||
Deleting the visual connector removes the `connects-to` annotation from the resources. Are | ||
you sure you want to delete the visual connector? | ||
</Trans> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
</p> | ||
); | ||
|
||
return confirmModal({ | ||
title: ( | ||
<> | ||
<YellowExclamationTriangleIcon className="co-icon-space-r" /> Delete Connector? | ||
<YellowExclamationTriangleIcon className="co-icon-space-r" />{' '} | ||
<Trans ns="topology">Delete Connector?</Trans> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
</> | ||
), | ||
message, | ||
btnText: 'Delete', | ||
btnText: <Trans ns="topology">Delete</Trans>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
@@ -17,6 +18,7 @@ type TopologyEdgeResourcesPanelProps = { | |||
}; | |||
|
|||
const TopologyEdgeResourcesPanel: React.FC<TopologyEdgeResourcesPanelProps> = ({ edge }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -38,7 +39,8 @@ export const AddHealthChecks = (model: K8sKind, obj: K8sResourceKind): KebabOpti | |||
|
|||
export const EditHealthChecks = (model: K8sKind, obj: K8sResourceKind): KebabOption => { | |||
return { | |||
label: 'Edit Health Checks', | |||
// t('console-app~Edit Health Checks') | |||
labelKey: 'Edit Health Checks', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
labelKey: 'Edit Health Checks', | |
labelKey: 'console-app~Edit Health Checks', |
{ready} of {desired} pods | ||
</Link> | ||
); | ||
return <Link to={href}>{t('topology~{{ready}} of {{desired}} pods', { ready, desired })}</Link>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return <Link to={href}>{t('topology~{{ready}} of {{desired}} pods', { ready, desired })}</Link>; | |
return <Link to={href}>{t('topology~{{ready, number}} of {{count, number}} pod', { ready, count: desired })}</Link>; |
6f69e98
to
36e3932
Compare
@andrewballantyne @vikram-raj Updated per comments. |
@@ -50,11 +53,11 @@ const StatusCellResourceStatus: React.FC<StatusCellResourceStatus> = ({ obj, pod | |||
if (!filteredPods.length) { | |||
return null; | |||
} | |||
return <Link to={href}>{filteredPods.length} pods</Link>; | |||
return <Link to={href}>{t('topology~{{length}} pods', { length: filteredPods.length })}</Link>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return <Link to={href}>{t('topology~{{length}} pods', { length: filteredPods.length })}</Link>; | |
return <Link to={href}>{t('topology~{{count, number}} pod', { count: filteredPods.length })}</Link>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/approve |
36e3932
to
e60f94e
Compare
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: andrewballantyne, christianvogt, jeff-phillips-18 The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Fixes: https://issues.redhat.com/browse/ODC-5130