Skip to content

fix(i18n): system-path JS translations, release POT extraction, locale-aware date picker#629

Merged
arifulhoque7 merged 1 commit into
weDevsOfficial:developfrom
arifulhoque7:fix/i18n-translation-and-shadcn-datepicker
Jul 3, 2026
Merged

fix(i18n): system-path JS translations, release POT extraction, locale-aware date picker#629
arifulhoque7 merged 1 commit into
weDevsOfficial:developfrom
arifulhoque7:fix/i18n-translation-and-shadcn-datepicker

Conversation

@arifulhoque7

@arifulhoque7 arifulhoque7 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the long-standing i18n issues reported against the plugin and standardizes date pickers on a single translatable shadcn calendar.

Root cause: React strings never reached the POT

The release makepot task (Gruntfile.js) excluded views/assets/src, so no React string was ever extracted to wedevs-project-manager.pot / translate.wordpress.org. Many strings were already wrapped in __() but had nothing to translate against. Now excludes views/assets/dist + vendor instead, matching package.json's makepot.

Changes

Issues

Fixes #560, #601
Refs #595, #597, #598, #600, #475, #470, #468

Testing

  • pnpm build clean; pnpm makepot now extracts React strings (verified Current Tasks, Templates, report descriptions present).
  • Verified on a local install with locale bn_BD: nav, breadcrumb, reports, and the calendar render in Bangla.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a richer, localized date picker across task, milestone, and report screens for easier date selection.
    • Introduced a calendar-based date experience with clear/today actions and date limits where applicable.
    • Added support for the new “Import Tools” navigation label.
  • Bug Fixes

    • Improved date handling to better preserve selected values across different locales and time zones.
    • Updated translation loading so plugin language files are picked up more reliably.
  • Documentation

    • Expanded translated labels in UI controls for a more consistent localized experience.

…e-aware date picker

- Load script (JS) translations from the WordPress system path
  (wp-content/languages/plugins/) before the bundled .mo, mirroring
  load_plugin_textdomain — React strings now honor user-supplied
  translations the same way PHP strings do (weDevsOfficial#560)
- Release makepot (Gruntfile) was excluding views/assets/src, so React
  strings never reached the POT / translate.wordpress.org. Exclude
  views/assets/dist + vendor instead — extraction now covers the React
  UI (weDevsOfficial#595, weDevsOfficial#597, weDevsOfficial#598, weDevsOfficial#600, weDevsOfficial#475)
- Translatable "Tools" / "Import Tools" nav + breadcrumb instead of the
  literal "Importtools" (weDevsOfficial#601)
- Wrap remaining shadcn ui primitive strings (pagination, dialog, sheet,
  color-picker) in __()
- Replace every native <input type="date"> with a shadcn react-day-picker
  DatePicker whose month/weekday/day labels localize via Intl(PM_Vars.locale);
  Today / Clear / dd-mm-yyyy are translatable
- Expose DatePicker + Calendar on window.PM.ui so Pro uses the same instance
- Regenerate POT and fill the bn_BD catalog

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Updates translation loading and POT generation, and adds a locale-aware date picker stack used across several UI screens.

Changes

Translation loading and extraction

Layer / File(s) Summary
POT excludes
Gruntfile.js
wp i18n make-pot now excludes views/assets/dist and vendor when generating languages/wedevs-project-manager.pot.
MO lookup order
libs/functions.php
wedevs_pm_get_translations_for_plugin_domain() now prefers WP_LANG_DIR/plugins/ before the plugin languages directory, and wedevs_pm_get_jed_locale_data() uses the filtered locale from determine_locale().

Date picker UI and shared i18n

Layer / File(s) Summary
Locale helpers and calendar
package.json, views/assets/src/lib/date-locale.js, views/assets/src/components/ui/calendar.jsx
react-day-picker is added, locale-based date formatters and week-start logic are added, and Calendar/CalendarDayButton wrap DayPicker.
DatePicker component
views/assets/src/components/ui/date-picker.jsx, views/assets/src/index.jsx
DatePicker adds ISO parsing/formatting, min/max bounds, calendar popover actions, and is re-exported through window.PM.ui.
My Tasks date controls
views/assets/src/components/my-tasks/MyTasksPage/index.jsx
The activity filter, report range controls, and task filter date inputs now use DatePicker and direct state updates.
Task forms
views/assets/src/components/my-tasks/MyTasksPage/parts/NewTaskSheet.jsx, views/assets/src/components/projects/MilestonesPage/parts/MilestoneForm.jsx, views/assets/src/components/tasks/TaskDetailSheet/index.jsx, views/assets/src/components/tasks/TaskListSection.jsx
The task sheet, milestone form, task detail dates editor, and task list due date field now use DatePicker instead of native date inputs.
Shared UI strings
views/assets/src/components/layout/TopBar.jsx, views/assets/src/components/ui/color-picker.jsx, views/assets/src/components/ui/dialog.jsx, views/assets/src/components/ui/pagination.jsx, views/assets/src/components/ui/sheet.jsx
Breadcrumb, color picker, dialog, pagination, and sheet labels now use @wordpress/i18n.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Needs Dev Review, Needs Testing

Suggested reviewers

  • iftakharul-islam

Poem

A bunny hopped through locale light,
With calendars trimmed just right.
“Clear” and “Today” rang soft and neat,
While date seeds bloomed in every seat.
🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: i18n loading, POT extraction, and the new locale-aware date picker.
Linked Issues check ✅ Passed The JS translation loader now checks the system language path first and then falls back to the bundled .mo file, matching #560.
Out of Scope Changes check ✅ Passed The changes stay within i18n, POT extraction, and date-picker localization work; no unrelated edits are evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
views/assets/src/components/ui/pagination.jsx (1)

83-88: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Move aria-hidden off the ellipsis wrapper.

Line 88’s translated sr-only text is still unreachable because the parent <span> is aria-hidden. That leaves the control purely decorative to assistive tech, so the new "More pages" label never gets announced.

Suggested fix
 const PaginationEllipsis = ({
   className,
   ...props
 }) => (
   <span
-    aria-hidden
     className={cn("flex h-9 w-9 items-center justify-center", className)}
     {...props}>
-    <MoreHorizontal className="h-4 w-4" />
+    <MoreHorizontal className="h-4 w-4" aria-hidden="true" />
     <span className="sr-only">{__('More pages', 'wedevs-project-manager')}</span>
   </span>
 )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@views/assets/src/components/ui/pagination.jsx` around lines 83 - 88, The
ellipsis control in the pagination component is hiding its accessible label
because the wrapper span in the pagination item is marked aria-hidden. Update
the PaginationEllipsis/PaginationItem markup so the decorative MoreHorizontal
icon stays hidden if needed, but the sr-only “More pages” text is not inside an
aria-hidden container and can be announced by assistive tech.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@views/assets/src/components/ui/calendar.jsx`:
- Around line 34-38: The month dropdown formatter in calendar.jsx is using the
browser default locale instead of the site/plugin locale, so update the
formatMonthDropdown callback inside the formatters object to use
getPmLocaleTag() from the date-locale helper. Import getPmLocaleTag in the
component and pass it to date.toLocaleString so the month labels match the rest
of the calendar and the active WordPress site locale.

In `@views/assets/src/components/ui/date-picker.jsx`:
- Around line 19-25: The parseISO helper currently accepts overflow dates
because new Date(y, m - 1, d) normalizes invalid inputs, so update parseISO to
validate the reconstructed date against the parsed year, month, and day before
returning it. Keep the existing guards in parseISO, then after creating the Date
object, compare its year/month/day components to the original y, m, and d and
return undefined unless they match exactly; this prevents impossible dates from
being accepted by the date-picker component.
- Around line 94-108: The “Today” action in date-picker.jsx bypasses the
existing range checks and can emit an out-of-bounds date. Update the Today
button handler in the date-picker component so it respects the same `min`/`max`
constraints used by the calendar grid before calling `emit`, and only emit today
when it falls within range; otherwise disable or no-op the action. Use the
existing `emit` logic and the component’s `min`/`max` props in the date-picker
UI to keep behavior consistent.

In `@views/assets/src/lib/date-locale.js`:
- Around line 3-18: The locale normalization in getPmLocaleTag only replaces the
first underscore, so Intl formatter setup can still receive invalid tags and
throw during module initialization. Update getPmLocaleTag to normalize full
WordPress slugs by converting all underscores to hyphens, and guard the
formatter initialization around tag, numberFmt, captionFmt, weekdayFmt, and
longDateFmt with a try/catch that falls back to en-US if Intl still rejects the
locale.

---

Outside diff comments:
In `@views/assets/src/components/ui/pagination.jsx`:
- Around line 83-88: The ellipsis control in the pagination component is hiding
its accessible label because the wrapper span in the pagination item is marked
aria-hidden. Update the PaginationEllipsis/PaginationItem markup so the
decorative MoreHorizontal icon stays hidden if needed, but the sr-only “More
pages” text is not inside an aria-hidden container and can be announced by
assistive tech.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55893c21-13b5-4201-8d0f-f12b92bf4f48

📥 Commits

Reviewing files that changed from the base of the PR and between 2077621 and 7044c50.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • Gruntfile.js
  • languages/wedevs-project-manager-bn_BD.mo
  • languages/wedevs-project-manager-bn_BD.po
  • libs/functions.php
  • package.json
  • views/assets/src/components/layout/TopBar.jsx
  • views/assets/src/components/my-tasks/MyTasksPage/index.jsx
  • views/assets/src/components/my-tasks/MyTasksPage/parts/NewTaskSheet.jsx
  • views/assets/src/components/projects/MilestonesPage/parts/MilestoneForm.jsx
  • views/assets/src/components/tasks/TaskDetailSheet/index.jsx
  • views/assets/src/components/tasks/TaskListSection.jsx
  • views/assets/src/components/ui/calendar.jsx
  • views/assets/src/components/ui/color-picker.jsx
  • views/assets/src/components/ui/date-picker.jsx
  • views/assets/src/components/ui/dialog.jsx
  • views/assets/src/components/ui/pagination.jsx
  • views/assets/src/components/ui/sheet.jsx
  • views/assets/src/index.jsx
  • views/assets/src/lib/date-locale.js

Comment on lines +34 to +38
formatters={{
formatMonthDropdown: (date) =>
date.toLocaleString("default", { month: "short" }),
...formatters,
}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n views/assets/src/components/ui/calendar.jsx

Repository: file_read:views/assets/src/components/ui/calendar.jsx

Length of output: 2143


🏁 Script executed:

grep -r "PM_Vars" views/assets/src --include="*.jsx" --include="*.js" | grep -i "locale\|site_user" | head -20

Repository: search_locale_usage

Length of output: 2041


🏁 Script executed:

grep -r "DayPicker" views/assets/src --include="*.jsx" --include="*.js" -A 5 -B 5 | grep -i "locale" | head -20

Repository: search_daypicker_locale

Length of output: 2053


🏁 Script executed:

cat -n views/assets/src/components/ui/calendar.jsx

Repository: weDevsOfficial/wp-project-manager

Length of output: 8399


🏁 Script executed:

grep -r "PM_Vars" views/assets/src --include="*.jsx" --include="*.js" | head -20

Repository: weDevsOfficial/wp-project-manager

Length of output: 3667


🏁 Script executed:

grep -r "locale" views/assets/src --include="*.jsx" --include="*.js" | head -20

Repository: weDevsOfficial/wp-project-manager

Length of output: 1884


🏁 Script executed:

cat -n views/assets/src/lib/date-locale.js

Repository: read_date_locale

Length of output: 2032


🏁 Script executed:

cat -n views/assets/src/lib/date-locale.js

Repository: weDevsOfficial/wp-project-manager

Length of output: 1764


Use the plugin locale for month dropdown labels.

formatMonthDropdown uses date.toLocaleString("default", ...) which relies on the browser's locale, causing month names in the dropdown to differ from the rest of the calendar if the user's browser setting differs from the WordPress site locale.

The codebase already provides views/assets/src/lib/date-locale.js with getPmLocaleTag() to retrieve the site's locale (e.g., bn-BD). Import this helper and pass the correct locale tag to toLocaleString:

import { getPmLocaleTag } from "`@/lib/date-locale`"

// Inside formatters
formatMonthDropdown: (date) =>
  date.toLocaleString(getPmLocaleTag(), { month: "short" }),

This ensures consistency with the getCaption formatter used elsewhere and aligns the dropdown with the active site configuration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@views/assets/src/components/ui/calendar.jsx` around lines 34 - 38, The month
dropdown formatter in calendar.jsx is using the browser default locale instead
of the site/plugin locale, so update the formatMonthDropdown callback inside the
formatters object to use getPmLocaleTag() from the date-locale helper. Import
getPmLocaleTag in the component and pass it to date.toLocaleString so the month
labels match the rest of the calendar and the active WordPress site locale.

Comment on lines +19 to +25
function parseISO(value) {
if (!value || typeof value !== 'string') return undefined
const [y, m, d] = value.split('-').map(Number)
if (!y || !m || !d) return undefined
const date = new Date(y, m - 1, d)
return isNaN(date.getTime()) ? undefined : date
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

python3 - <<'PY'
import datetime

# Simulate JS Date behavior for overflow
# JS: new Date(2026, 1, 31) -> 2026-03-03 (Feb has 28 days in 2026)
# Python: datetime(2026, 2, 31) throws error. We need to simulate JS overflow.

def js_date(y, m, d):
    """Simulate JS new Date(y, m, d) behavior where m is 0-indexed."""
    # In JS, months are 0-indexed. m-1 in the code converts string month to JS index.
    # So new Date(2026, 1, 31) is Feb 31.
    # JS automatically rolls over: Feb 31 = Mar 3 (non-leap year)
    try:
        # We can't easily simulate JS overflow in Python without a library, 
        # but we know the behavior: new Date(2026, 1, 31) -> 2026-03-03
        # Let's just prove the logic of the fix using Python's safe date
        # The fix logic is: if the date we get back doesn't match what we put in, it's invalid.
        
        # Test case 1: Valid date
        test_y, test_m, test_d = 2026, 1, 31 # Feb 31 (invalid)
        # JS would interpret this as March 3rd.
        # So: JS_New_Date(2026, 1, 31) -> Mar 3, 2026
        # Fetching components:
        # JS_Get_Year() -> 2026
        # JS_Get_Month() -> 2 (March, 0-indexed)
        # JS_Get_Date() -> 3
        # Check: 2026==2026 (ok), 2==1 (FAIL), 3==31 (FAIL). -> Returns undefined. Correct.
        
        # Test case 2: Valid date
        # JS_New_Date(2026, 0, 31) -> Jan 31
        # Components: 2026, 0, 31
        # Check: 2026==2026, 0==0, 31==31. -> Returns date. Correct.
        
        print("Logic verification:")
        print("Case 1 (Invalid Feb 31): Input (2026, 1, 31). JS rolls to Mar 3 (2, 3).")
        print("  Check: year 2026==2026, month 2!=1, date 3!=31. Fix returns undefined. CORRECT.")
        print("Case 2 (Valid Jan 31): Input (2026, 0, 31).")
        print("  Check: year 2026==2026, month 0==0, date 31==31. Fix returns date. CORRECT.")
        print("Conclusion: The proposed fix logic is sound for catching JS Date normalization.")
    except Exception as e:
        print(f"Error: {e}")
PY

Repository: weDevsOfficial/wp-project-manager

Length of output: 171


Reject overflow dates in parseISO.

JavaScript's new Date(y, m - 1, d) silently normalizes impossible dates. For instance, 2026-02-31 becomes 2026-03-03, causing the UI to display a different date than the stored value and allowing invalid data to persist.

Replace the current validation with a component check to ensure the reconstructed date matches the input exactly:

Suggested fix
 function parseISO(value) {
   if (!value || typeof value !== 'string') return undefined
   const [y, m, d] = value.split('-').map(Number)
   if (!y || !m || !d) return undefined
   const date = new Date(y, m - 1, d)
-  return isNaN(date.getTime()) ? undefined : date
+  if (isNaN(date.getTime())) return undefined
+  if (
+    date.getFullYear() !== y ||
+    date.getMonth() !== m - 1 ||
+    date.getDate() !== d
+  ) {
+    return undefined
+  }
+  return date
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function parseISO(value) {
if (!value || typeof value !== 'string') return undefined
const [y, m, d] = value.split('-').map(Number)
if (!y || !m || !d) return undefined
const date = new Date(y, m - 1, d)
return isNaN(date.getTime()) ? undefined : date
}
function parseISO(value) {
if (!value || typeof value !== 'string') return undefined
const [y, m, d] = value.split('-').map(Number)
if (!y || !m || !d) return undefined
const date = new Date(y, m - 1, d)
if (isNaN(date.getTime())) return undefined
if (
date.getFullYear() !== y ||
date.getMonth() !== m - 1 ||
date.getDate() !== d
) {
return undefined
}
return date
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@views/assets/src/components/ui/date-picker.jsx` around lines 19 - 25, The
parseISO helper currently accepts overflow dates because new Date(y, m - 1, d)
normalizes invalid inputs, so update parseISO to validate the reconstructed date
against the parsed year, month, and day before returning it. Keep the existing
guards in parseISO, then after creating the Date object, compare its
year/month/day components to the original y, m, and d and return undefined
unless they match exactly; this prevents impossible dates from being accepted by
the date-picker component.

Comment on lines +94 to +108
<div className="flex items-center justify-between border-t border-pm-border px-3 py-2">
<button
type="button"
className="text-sm font-medium text-pm-accent hover:underline"
onClick={() => emit(undefined)}
>
{__('Clear', 'wedevs-project-manager')}
</button>
<button
type="button"
className="text-sm font-medium text-pm-accent hover:underline"
onClick={() => emit(new Date())}
>
{__('Today', 'wedevs-project-manager')}
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Honor min/max when the user clicks “Today”.

The grid disables out-of-range days, but Line 105 bypasses that and emits new Date() unconditionally. Any caller using min/max to enforce valid ranges can still receive an invalid value through this shortcut.

Suggested fix
   const minDate = parseISO(min)
   const maxDate = parseISO(max)
+  const today = parseISO(toISO(new Date()))
+  const todayDisabled =
+    (today && minDate && today < minDate) ||
+    (today && maxDate && today > maxDate)

   const disabledMatcher =
     minDate || maxDate ? { ...(minDate && { before: minDate }), ...(maxDate && { after: maxDate }) } : undefined
...
           <button
             type="button"
+            disabled={todayDisabled}
             className="text-sm font-medium text-pm-accent hover:underline"
-            onClick={() => emit(new Date())}
+            onClick={() => emit(today)}
           >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@views/assets/src/components/ui/date-picker.jsx` around lines 94 - 108, The
“Today” action in date-picker.jsx bypasses the existing range checks and can
emit an out-of-bounds date. Update the Today button handler in the date-picker
component so it respects the same `min`/`max` constraints used by the calendar
grid before calling `emit`, and only emit today when it falls within range;
otherwise disable or no-op the action. Use the existing `emit` logic and the
component’s `min`/`max` props in the date-picker UI to keep behavior consistent.

Comment on lines +3 to +18
export function getPmLocaleTag() {
const raw =
typeof PM_Vars !== 'undefined' && PM_Vars.locale ? PM_Vars.locale : 'en_US'
return raw.replace('_', '-')
}

const tag = getPmLocaleTag()

const numberFmt = new Intl.NumberFormat(tag)
const captionFmt = new Intl.DateTimeFormat(tag, { month: 'long', year: 'numeric' })
const weekdayFmt = new Intl.DateTimeFormat(tag, { weekday: 'short' })
const longDateFmt = new Intl.DateTimeFormat(tag, {
day: '2-digit',
month: '2-digit',
year: 'numeric',
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major

Normalize full WordPress locale slugs before creating Intl formatters.

The current raw.replace('_', '-') only swaps the first separator, causing Intl constructors to throw RangeError for locales with multiple underscores (e.g., de_DE_formal becomes invalid de-DE_formal). This breaks module import and crashes the application on screens using this helper.

Use replaceAll('_', '-') to convert all separators to BCP 47 format, and wrap the initialization in a try...catch to safely fallback to en-US if an invalid tag persists.

Suggested fix
 export function getPmLocaleTag() {
   const raw =
     typeof PM_Vars !== 'undefined' && PM_Vars.locale ? PM_Vars.locale : 'en_US'
-  return raw.replace('_', '-')
+  const normalized = raw.replaceAll('_', '-')
+
+  try {
+    new Intl.DateTimeFormat(normalized)
+    return normalized
+  } catch {
+    return 'en-US'
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function getPmLocaleTag() {
const raw =
typeof PM_Vars !== 'undefined' && PM_Vars.locale ? PM_Vars.locale : 'en_US'
return raw.replace('_', '-')
}
const tag = getPmLocaleTag()
const numberFmt = new Intl.NumberFormat(tag)
const captionFmt = new Intl.DateTimeFormat(tag, { month: 'long', year: 'numeric' })
const weekdayFmt = new Intl.DateTimeFormat(tag, { weekday: 'short' })
const longDateFmt = new Intl.DateTimeFormat(tag, {
day: '2-digit',
month: '2-digit',
year: 'numeric',
})
export function getPmLocaleTag() {
const raw =
typeof PM_Vars !== 'undefined' && PM_Vars.locale ? PM_Vars.locale : 'en_US'
const normalized = raw.replaceAll('_', '-')
try {
new Intl.DateTimeFormat(normalized)
return normalized
} catch {
return 'en-US'
}
}
const tag = getPmLocaleTag()
const numberFmt = new Intl.NumberFormat(tag)
const captionFmt = new Intl.DateTimeFormat(tag, { month: 'long', year: 'numeric' })
const weekdayFmt = new Intl.DateTimeFormat(tag, { weekday: 'short' })
const longDateFmt = new Intl.DateTimeFormat(tag, {
day: '2-digit',
month: '2-digit',
year: 'numeric',
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@views/assets/src/lib/date-locale.js` around lines 3 - 18, The locale
normalization in getPmLocaleTag only replaces the first underscore, so Intl
formatter setup can still receive invalid tags and throw during module
initialization. Update getPmLocaleTag to normalize full WordPress slugs by
converting all underscores to hyphens, and guard the formatter initialization
around tag, numberFmt, captionFmt, weekdayFmt, and longDateFmt with a try/catch
that falls back to en-US if Intl still rejects the locale.

@arifulhoque7 arifulhoque7 merged commit 73f0180 into weDevsOfficial:develop Jul 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Loading .mo files for this plugin

1 participant