Skip to content

NO-JIRA: fix: Proper translation for time units.#227

Open
alanconway wants to merge 1 commit intoopenshift:mainfrom
alanconway:translate-time-units
Open

NO-JIRA: fix: Proper translation for time units.#227
alanconway wants to merge 1 commit intoopenshift:mainfrom
alanconway:translate-time-units

Conversation

@alanconway
Copy link
Contributor

Separate time unit text ("seconds", "minutes" etc.) from time.ts logic.
Use t() translation for time unit labels.

Separate time unit text ("seconds", "minutes" etc.) from time.ts logic.
Use t() translation for time unit labels.
@openshift-ci-robot
Copy link

@alanconway: This pull request explicitly references no jira issue.

Details

In response to this:

Separate time unit text ("seconds", "minutes" etc.) from time.ts logic.
Use t() translation for time unit labels.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 18, 2026
@openshift-ci openshift-ci bot requested review from shwetaap and zhuje March 18, 2026 23:56
@openshift-ci
Copy link

openshift-ci bot commented Mar 18, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: alanconway

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 18, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2026

Walkthrough

The PR refactors the time unit system from a class-based approach to a numeric enum, introduces a new hook for localized time unit labels, adds date formatting utilities, updates affected components and tests, and extends localization files with new time unit keys.

Changes

Cohort / File(s) Summary
Core time module refactor
web/src/time.ts
Converts Unit from a class to a numeric enum with SECOND, MINUTE, HOUR, DAY, WEEK constants. Restructures exports to use a units array with destructuring for backward compatibility. Adds formatDate utility for YYYY-MM-DD HH:mm formatting. Updates Duration.duration() to multiply by unit directly instead of unit.value.
Localization expansion
web/locales/en/plugin__troubleshooting-panel-console-plugin.json
Adds five new localization keys (days, hours, minutes, seconds, weeks) for time unit translations.
Time unit label hook
web/src/hooks/useTimeUnitLabel.tsx
New React hook providing localized labels for time units by mapping Unit enum values to translated strings using i18n.
Component refactors
web/src/components/TimeRangeDropdown.tsx, web/src/components/TimeUnitPicker.tsx
Updates to use useTimeUnitLabel hook for localized unit displays. TimeRangeDropdown now formats durations as "Last N [unit]" and ranges with formatDate. TimeUnitPicker uses localized labels and handles Unit enum values directly in Select control.
Test updates
web/src/__tests__/time.spec.ts
Refactors imports to use named exports (Unit, Duration, SECOND, MINUTE, HOUR, DAY, WEEK, units). Replaces class-based Unit tests with enum value checks. Adds new tests for setTime, copyTime, isValidDate, and formatDate utilities. Adds units array ordering verification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci
Copy link

openshift-ci bot commented Mar 19, 2026

@alanconway: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/hooks/useTimeUnitLabel.tsx`:
- Around line 5-14: The hook useTimeUnitLabel currently returns only plural
labels and should be changed to produce count-aware, fully assembled duration
phrases: change useTimeUnitLabel to return a formatter function with signature
(unit: Unit, count: number) => string (or export a new formatTimeUnit(unit,
count) helper) that calls the i18n t(...) with the count parameter
(pluralization) and returns the complete localized phrase (e.g., "Last 1 hour"
or localized equivalent) instead of raw labels; then update callers (e.g., where
code builds `Last ${period.count} ${timeUnitLabel(period.unit)}`) to call the
new formatter with period.unit and period.count; also add/update the translation
keys to accept count-based/pluralized strings and allow translators to control
word order and inflection.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e7347ecb-7a1f-4b99-8a46-79aa895eabb5

📥 Commits

Reviewing files that changed from the base of the PR and between 983fd65 and d061006.

📒 Files selected for processing (6)
  • web/locales/en/plugin__troubleshooting-panel-console-plugin.json
  • web/src/__tests__/time.spec.ts
  • web/src/components/TimeRangeDropdown.tsx
  • web/src/components/TimeUnitPicker.tsx
  • web/src/hooks/useTimeUnitLabel.tsx
  • web/src/time.ts

Comment on lines +5 to +14
export const useTimeUnitLabel = (): ((u: Unit) => string) => {
const { t } = useTranslation('plugin__troubleshooting-panel-console-plugin');
const labels = new Map<Unit, string>([
[Unit.SECOND, t('seconds')],
[Unit.MINUTE, t('minutes')],
[Unit.HOUR, t('hours')],
[Unit.DAY, t('days')],
[Unit.WEEK, t('weeks')],
]);
return (u: Unit) => labels.get(u) ?? '';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find web -type f -name "useTimeUnitLabel.tsx" -o -name "TimeRangeDropdown.tsx" -o -name "TimeUnitPicker.tsx"

Repository: openshift/troubleshooting-panel-console-plugin

Length of output: 203


🏁 Script executed:

cat -n web/src/hooks/useTimeUnitLabel.tsx

Repository: openshift/troubleshooting-panel-console-plugin

Length of output: 747


🏁 Script executed:

cat -n web/src/components/TimeRangeDropdown.tsx | head -200

Repository: openshift/troubleshooting-panel-console-plugin

Length of output: 7529


🏁 Script executed:

cat -n web/src/components/TimeUnitPicker.tsx

Repository: openshift/troubleshooting-panel-console-plugin

Length of output: 1706


Use count-aware pluralization and assembled phrases instead of hardcoded plural labels.

The hook exposes only plural forms (lines 8-12). Line 192 in web/src/components/TimeRangeDropdown.tsx builds Last ${period.count} ${timeUnitLabel(period.unit)}, which produces grammatically incorrect output for singular values (Last 1 hours, Last 1 days). Additionally, translators cannot fix word order or inflection because duration phrases are assembled from fragments. Make this API count-aware and compose fully translated duration strings in callers instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/hooks/useTimeUnitLabel.tsx` around lines 5 - 14, The hook
useTimeUnitLabel currently returns only plural labels and should be changed to
produce count-aware, fully assembled duration phrases: change useTimeUnitLabel
to return a formatter function with signature (unit: Unit, count: number) =>
string (or export a new formatTimeUnit(unit, count) helper) that calls the i18n
t(...) with the count parameter (pluralization) and returns the complete
localized phrase (e.g., "Last 1 hour" or localized equivalent) instead of raw
labels; then update callers (e.g., where code builds `Last ${period.count}
${timeUnitLabel(period.unit)}`) to call the new formatter with period.unit and
period.count; also add/update the translation keys to accept
count-based/pluralized strings and allow translators to control word order and
inflection.

Comment on lines +190 to +198
const labelFromPeriod = (period: time.Period, t: TFunction): string => {
if (period instanceof time.Duration) {
return `${t('Last')} ${period.count} ${timeUnitLabel(period.unit)}`;
}
if (period instanceof time.Range) {
return `${time.formatDate(period.start)} – ${time.formatDate(period.end)}`;
}
return t('Custom');
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const labelFromPeriod = (period: time.Period, t: TFunction): string => {
if (period instanceof time.Duration) {
return `${t('Last')} ${period.count} ${timeUnitLabel(period.unit)}`;
}
if (period instanceof time.Range) {
return `${time.formatDate(period.start)}${time.formatDate(period.end)}`;
}
return t('Custom');
};
const labelFromPeriod = React.useCallback((period: time.Period, t: TFunction): string => {
if (period instanceof time.Duration) {
return `${t('Last')} ${period.count} ${timeUnitLabel(period.unit)}`;
}
if (period instanceof time.Range) {
return `${time.formatDate(period.start)}${time.formatDate(period.end)}`;
}
return t('Custom');
}, [timeUnitLabel]);

Comment on lines +7 to +14
const labels = new Map<Unit, string>([
[Unit.SECOND, t('seconds')],
[Unit.MINUTE, t('minutes')],
[Unit.HOUR, t('hours')],
[Unit.DAY, t('days')],
[Unit.WEEK, t('weeks')],
]);
return (u: Unit) => labels.get(u) ?? '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const labels = new Map<Unit, string>([
[Unit.SECOND, t('seconds')],
[Unit.MINUTE, t('minutes')],
[Unit.HOUR, t('hours')],
[Unit.DAY, t('days')],
[Unit.WEEK, t('weeks')],
]);
return (u: Unit) => labels.get(u) ?? '';
return React.useCallback(
(u: Unit): string => {
switch (u) {
case Unit.SECOND: return t('seconds');
case Unit.MINUTE: return t('minutes');
case Unit.HOUR: return t('hours');
case Unit.DAY: return t('days');
case Unit.WEEK: return t('weeks');
default: return '';
}
},
[t]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants