Skip to content

Centralize JS translations in skin.js.php with zmPrimeTranslations() for lazy priming#4804

Open
Copilot wants to merge 5 commits into
masterfrom
copilot/improve-js-translations
Open

Centralize JS translations in skin.js.php with zmPrimeTranslations() for lazy priming#4804
Copilot wants to merge 5 commits into
masterfrom
copilot/improve-js-translations

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 6, 2026

Each *.js.php view file independently defined a translate JS object and common translated string constants, duplicating the same keys across multiple files with inconsistent escaping.

Changes

  • skin.js.php — Defines an empty translate object and a zmPrimeTranslations(t) helper (calls Object.assign(translate, t)) that any file can call to register translations without overwriting the shared object. Primes all common translations in one place, including alarm-related keys (EnableAlarms, DisableAlarms, ForceAlarm, CancelForcedAlarm) that MonitorStream.js needs across multiple views. Also defines common standalone string constants (deleteString, archivedString, unarchivedString, emailedString, yesString, noString, confirmDeleteEventsString), all using validJsStr() uniformly.

  • Removed from view files — Deleted the per-view var translate = {...} definitions from watch.js.php, event.js.php, and zone.js.php. Removed duplicated standalone string constants from event.js.php, events.js.php, snapshot.js.php, snapshots.js.php, timeline.js.php, watch.js.php, and zone.js.php.

  • Per-view priming patternevent.js.php demonstrates the pattern by calling zmPrimeTranslations({"Show Zones": "...", "Hide Zones": "..."}) for its page-specific keys; event.js accesses them via translate["Show Zones"] / translate["Hide Zones"].

  • MonitorStream.js — Updated 8 references from standalone variables (enableAlarmsStr etc.) to translate["EnableAlarms"] etc., since MonitorStream.js is loaded across 5 different views.

After — common translations registered once in skin.js.php:

const translate = {};
function zmPrimeTranslations(t) { Object.assign(translate, t); }
zmPrimeTranslations({
  "seconds": "...",
  "Fullscreen": "...",
  "EnableAlarms": "...",
  // all common keys...
});

Per-view additions in a view's .js.php:

zmPrimeTranslations({
  "Show Zones": "<?php echo validJsStr(translate('Show Zones')) ?>",
  "Hide Zones": "<?php echo validJsStr(translate('Hide Zones')) ?>",
});

The Object.assign approach makes zmPrimeTranslations additive and safe to call multiple times, laying the groundwork for future AJAX-loaded translations.

Copilot AI and others added 2 commits May 6, 2026 01:53
… skin.js.php refs #4290

Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/f8ffacbf-358b-47f5-a732-afdd9e5854a8

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve centralized handling of JS text translations Centralize JS translations in skin.js.php instead of per-view redefinition May 6, 2026
Copilot AI requested a review from connortechnology May 6, 2026 01:55
@connortechnology
Copy link
Copy Markdown
Member

@copilot it would be nice if they would lazy load on use... and perhaps in each .js.php or even .js, we could call a function to prime it

Copilot AI and others added 2 commits May 6, 2026 02:43
…er view refs #4290

Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/3607efe7-9a75-41ed-82f3-e4975e4c3654

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
Agent-Logs-Url: https://github.com/ZoneMinder/zoneminder/sessions/3607efe7-9a75-41ed-82f3-e4975e4c3654

Co-authored-by: connortechnology <925519+connortechnology@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 6, 2026

@copilot it would be nice if they would lazy load on use... and perhaps in each .js.php or even .js, we could call a function to prime it

Done in commit 6aeaba5. Here's how the lazy-priming pattern works:

skin.js.php defines the empty registry and the priming function, then registers common translations:

const translate = {};
function zmPrimeTranslations(t) { Object.assign(translate, t); }
zmPrimeTranslations({
  "Fullscreen": "...",
  "EnableAlarms": "...",
  // all common keys...
});

Any view's .js.php file can now prime its own page-specific translations without touching the global object — e.g. event.js.php:

zmPrimeTranslations({
  "Show Zones": "<?php echo validJsStr(translate('Show Zones')) ?>",
  "Hide Zones": "<?php echo validJsStr(translate('Hide Zones')) ?>",
});

And the static event.js accesses them via translate["Show Zones"].

The Object.assign approach is intentional: it merges keys in, so calling zmPrimeTranslations multiple times is safe and additive — which makes it easy to extend with AJAX-loaded translations in the future.

Copilot AI changed the title Centralize JS translations in skin.js.php instead of per-view redefinition Centralize JS translations in skin.js.php with zmPrimeTranslations() for lazy priming May 6, 2026
Copy link
Copy Markdown
Member

@connortechnology connortechnology left a comment

Choose a reason for hiding this comment

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

Reviewed the diff — solid cleanup, the additive Object.assign(translate, t) pattern is the right shape and the per-view priming via zmPrimeTranslations({...}) reads cleanly. Load order checks out (skin.js.php is require_once'd before view .js.php files, then external skin.js loads before view-specific JS), and I grepped — every reference to the removed globals (enableAlarmsStr/disableAlarmsStr/forceAlarmStr/cancelForcedAlarmStr/showZonesString/hideZonesString plus the standalone strings) is updated in this PR.

A few items worth addressing before merge:

1. Alarm strings don't really belong in skin.js.php

EnableAlarms / DisableAlarms / ForceAlarm / CancelForcedAlarm are only consumed by MonitorStream.js. Loading them in skin.js.php means every page (including non-monitor pages like options, console, events list, etc.) pays for them. The whole point of the lazy-priming pattern is to let each view register what it actually needs — these belong in watch.js.php / montage.js.php / wherever MonitorStream is actually instantiated. Same comment applies if other "common" keys turn out to be view-specific.

2. zmPrimeTranslations name reads like a one-shot

"Prime" suggests initialize-once, but the function is explicitly designed to be additive across many calls (which is the whole point — that's what makes event.js.php adding Show Zones/Hide Zones after skin.js.php already primed common keys work). Consider zmAddTranslations or zmRegisterTranslations so the additive contract is in the name.

3. Style tidy in the same touched files

The new declarations in skin.js.php are const, but leftover declarations in the touched .js.php files (e.g. var causeString = ... in both event.js.php and snapshot.js.php, plus var WEB_LIST_THUMB_*, var popup) are still var. Worth flipping to const while you're in the file.

4. Escape function change benign but worth a note

confirmDeleteEventsString moves from addslashes() to validJsStr() (= strip_tags(addslashes())). Strictly stronger and risk-free for translation strings that don't intentionally embed HTML. Just worth a one-line mention in the PR description so a future reader doesn't wonder.

5. Run ESLint

npx eslint . from the repo root — make sure no rule trips on the const-object mutation pattern or the cross-file reference to a now-undeclared-in-this-file translate.

(1) and (5) are the only things I'd consider hard blockers. (2)/(3)/(4) are polish.

@connortechnology connortechnology marked this pull request as ready for review May 18, 2026 22:38
Copilot AI review requested due to automatic review settings May 18, 2026 22:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR centralizes shared JavaScript translation setup for the classic skin, reducing duplicated per-view translation definitions and moving common strings into skin.js.php.

Changes:

  • Adds a shared translate object and zmPrimeTranslations() helper in skin.js.php.
  • Removes duplicated common translation variables from multiple views/js/*.js.php files.
  • Updates event and monitor stream JavaScript to read translated labels from the shared translate object.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
web/skins/classic/js/skin.js.php Adds shared translation constants/object and priming helper.
web/js/MonitorStream.js Switches alarm button titles to shared translation lookups.
web/skins/classic/views/js/event.js.php Removes duplicated strings and primes event-specific zone translations.
web/skins/classic/views/js/event.js Uses shared translations for zone toggle titles.
web/skins/classic/views/js/watch.js.php Removes duplicated translation definitions.
web/skins/classic/views/js/zone.js.php Removes duplicated translation definitions.
web/skins/classic/views/js/events.js.php Removes duplicated list/action translation constants.
web/skins/classic/views/js/snapshot.js.php Removes duplicated delete string.
web/skins/classic/views/js/snapshots.js.php Removes duplicated snapshot list translation constants.
web/skins/classic/views/js/timeline.js.php Removes duplicated archived string.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const translate = {};
function zmPrimeTranslations(t) { Object.assign(translate, t); }
zmPrimeTranslations({
"seconds": "<?php echo translate('seconds') ?>",
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.

Improvement: The "translate" variable for translating JS text is defined in each *.js.php file.

3 participants