Skip to content

feat(PdfReader): support localization#733

Merged
ArgoZhang merged 9 commits intomasterfrom
dev-fs
Nov 27, 2025
Merged

feat(PdfReader): support localization#733
ArgoZhang merged 9 commits intomasterfrom
dev-fs

Conversation

@ArgoZhang
Copy link
Copy Markdown
Member

@ArgoZhang ArgoZhang commented Nov 27, 2025

Link issues

fixes #732

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Localize and enhance the PdfReader toolbar and viewer controls, including dropdown behavior and thumbnail rendering.

New Features:

  • Add localization support to PdfReader via IStringLocalizer, including localized titles and labels for toolbar controls and menu items.
  • Introduce an optional Presentation Mode control in the PdfReader toolbar that can be toggled via a new ShowPresentationMode parameter.

Enhancements:

  • Refine the PdfReader toolbar and dropdown UI, including icon/active state handling for two-page view and other menu items, and removal of the toolbar init/visibility hack.
  • Improve thumbnail rendering in the PdfReader sidebar by wrapping images in a group element and displaying page number labels below each thumbnail.

Copilot AI review requested due to automatic review settings November 27, 2025 07:02
@bb-auto bb-auto Bot added the enhancement New feature or request label Nov 27, 2025
@bb-auto bb-auto Bot added this to the v9.2.0 milestone Nov 27, 2025
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Nov 27, 2025

Reviewer's Guide

Adds localization support and UI affordances to the PdfReader component while simplifying two-page view wiring and enhancing thumbnails and dropdown behavior.

Sequence diagram for two page view toggle in PdfReader toolbar

sequenceDiagram
    actor User
    participant PdfReaderToolbar as PdfReaderToolbar
    participant PdfReaderJs as PdfReader_razor_js
    participant PdfViewer

    User->>PdfReaderToolbar: Click dropdown-item-pages
    PdfReaderToolbar->>PdfReaderJs: DOM click event on .dropdown-item-pages
    PdfReaderJs->>PdfReaderJs: Toggle active class on clicked item
    alt spreadMode is not 1
        PdfReaderJs->>PdfViewer: set spreadMode = 1
    else spreadMode is 1
        PdfReaderJs->>PdfViewer: set spreadMode = 0
    end
Loading

Class diagram for updated PdfReader localization and view options

classDiagram
    class PdfReader {
        +bool ShowToolbar
        +bool ShowDownload
        +bool ShowPrint
        +bool ShowTwoPagesOneView
        +bool ShowPresentationMode
        +bool EnableTwoPagesOneView
        +uint CurrentPage
        +string CurrentScale
        +string Url
        +string? MoreButtonIcon
        +Func~Task~ OnPrintingAsync
        +EventCallback OnDownload
        +EventCallback OnPrinted
        -uint _currentPage
        -string _currentScale
        -string _url
        -string _dropdownItemCheckIcon
        -string _dropdownItemDefaultIcon
        -IStringLocalizer_PdfReader_ Localizer
        +string CurrentPageString
        +string CurrentScaleString
        +override void OnParametersSet()
        +override Task OnAfterRenderAsync(bool firstRender)
        +void SetFitMode(PdfReaderFitMode mode)
        +void RotateLeft()
        +void RotateRight()
    }

    class PdfReaderFitMode {
        <<enumeration>>
        PageActual
        PageWidth
        PageHeight
        PageFit
        Auto
    }

    PdfReader --> PdfReaderFitMode : uses
Loading

File-Level Changes

Change Details Files
Wire PdfReader toolbar controls directly in JS event handler and extend UI behaviors for two-page view and presentation mode.
  • Remove setPages helper and resetTwoPagesOneView function, inlining spreadMode toggling into a new click handler on .dropdown-item-pages within the controls container.
  • Attach new click handlers for .dropdown-item-pages and .dropdown-item-presentation that toggle the active class and update pdfViewer.spreadMode for two-page view while stubbing presentation mode behavior.
  • Convert the print button handler to async to invoke the Blazor Printing callback.
  • Adjust pagesinit handler by removing the toolbar init class manipulation and simplifying scale-related element selection.
  • Wrap thumbnail image and new page number label in a .bb-view-thumbnail-group container to support improved styling.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Localize PdfReader toolbar labels and restructure dropdown items for view modes, presentation mode, and document properties.
  • Add Localizer-based titles/tooltips and display strings for sidebar toggle, zoom in/out, fit height/width, rotation, download, and print icons.
  • Simplify fit-mode dropdown to use localized labels and remove unused options like PageFit and Auto.
  • Refactor the More dropdown menu to use common check/default icons for items, change Two pages on view to a localized TwoPageView entry without direct @OnClick, and add optional PresentationMode and DocumentProperty entries based on new parameters.
  • Introduce a dedicated CSS class on the dropdown menu (bb-view-dropdown-menu) and structural changes inside dropdown items to support checkmark styling and localization.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor
Introduce localization dependency and new presentation mode flag while removing obsolete two-page-view state synchronization logic.
  • Inject IStringLocalizer into the component to drive localized UI text.
  • Add ShowPresentationMode parameter to control visibility of the Presentation Mode dropdown item.
  • Replace the old _twoPagesOneViewIcon and client-synced two-page-view state with shared _dropdownItemCheckIcon and _dropdownItemDefaultIcon fields used by multiple dropdown items.
  • Remove OnToggleTwoPagesOneView and all OnAfterRenderAsync calls that were synchronizing EnableTwoPagesOneView and ShowTwoPagesOneView to JavaScript via setPages, since the JS now handles toggling directly.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
Adjust PdfReader CSS to support the new dropdown behavior and improved thumbnail layout while removing obsolete toolbar initialization styling.
  • Remove the .bb-view-toolbar.init visibility-hiding rule now that the init class is no longer used.
  • Customize toolbar dropdown-menu variables to keep active-item background transparent and use standard text color for active states.
  • Add styles to toggle visibility between .dropdown-item-check and .dropdown-item-icon based on the dropdown-item active state, enabling a checkmark for selected options.
  • Improve thumbnail appearance by centering canvases, wrapping them in .bb-view-thumbnail-group, and styling the label text under thumbnails.
src/components/BootstrapBlazor.PdfReader/PdfReader.razor.css
Add localization resource placeholders for English and Chinese for the PdfReader component.
  • Introduce en.json and zh.json locale files in the PdfReader Locales folder to define localized strings referenced by the component.
  • Ensure the project structure is ready for per-locale resource expansion, even if the csproj changes are minimal or not shown in detail.
src/components/BootstrapBlazor.PdfReader/BootstrapBlazor.PdfReader.csproj
src/components/BootstrapBlazor.PdfReader/Locales/en.json
src/components/BootstrapBlazor.PdfReader/Locales/zh.json

Assessment against linked issues

Issue Objective Addressed Explanation
#732 Enable the PdfReader component to use localization by wiring in an IStringLocalizer and replacing hardcoded UI strings with localized resources.
#732 Provide localization resource files for PdfReader (e.g., for at least English and Chinese) so that the localized keys resolve at runtime.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

Blocking issues:

  • User controlled data in methods like innerHTML, outerHTML or document.write is an anti-pattern that can lead to XSS vulnerabilities (link)
  • User controlled data in a label.innerHTML is an anti-pattern that can lead to XSS vulnerabilities (link)

General comments:

  • In PdfReader.razor.js, the minus/plus element queries were removed from the pagesinit handler, but the variables are still referenced later in the same function when attaching click handlers, which will cause a runtime error; either restore the queries or move them to a shared scope that is still valid.
  • The EnableTwoPagesOneView and ShowTwoPagesOneView parameters are no longer wired to any JavaScript calls or internal state updates (the Blazor-side toggle handler was removed and the JS now manages state purely via CSS classes), which can lead to confusion or stale API surface; consider either re-synchronizing these parameters with the client state or deprecating/removing them if they are no longer meant to control behavior.
  • The presentation mode dropdown item currently only toggles the .active class and has its fullscreen logic commented out; if this is intended to be a functional feature rather than a placeholder, consider either implementing the fullscreen behavior or clearly separating it as a future enhancement to avoid a non-functional UI control.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In PdfReader.razor.js, the `minus`/`plus` element queries were removed from the `pagesinit` handler, but the variables are still referenced later in the same function when attaching click handlers, which will cause a runtime error; either restore the queries or move them to a shared scope that is still valid.
- The `EnableTwoPagesOneView` and `ShowTwoPagesOneView` parameters are no longer wired to any JavaScript calls or internal state updates (the Blazor-side toggle handler was removed and the JS now manages state purely via CSS classes), which can lead to confusion or stale API surface; consider either re-synchronizing these parameters with the client state or deprecating/removing them if they are no longer meant to control behavior.
- The presentation mode dropdown item currently only toggles the `.active` class and has its fullscreen logic commented out; if this is intended to be a functional feature rather than a placeholder, consider either implementing the fullscreen behavior or clearly separating it as a future enhancement to avoid a non-functional UI control.

## Individual Comments

### Comment 1
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:125-134` </location>
<code_context>
+                pdfViewer.spreadMode = 0;
+            }
+        });
+        EventHandler.on(controls, "click", ".dropdown-item-presentation", async e => {
+            e.delegateTarget.classList.toggle("active");
+
+            //if (pdfViewer.isInPresentationMode) {
+            //    document.exitFullscreen();
+            //}
+            //else {
+            //    el.requestFullscreen();
+            //}
+        });
</code_context>

<issue_to_address>
**suggestion (bug_risk):** The presentation mode dropdown currently only toggles CSS state and doesn’t affect the actual viewer presentation mode.

The click handler for `.dropdown-item-presentation` only toggles the `active` class; the code that actually enters/exits fullscreen (`pdfViewer` presentation mode) is fully commented out. Consider either wiring this handler to `pdfViewer`’s presentation/fullscreen API and keeping the UI state in sync, or gating this menu item behind `ShowPresentationMode` (or similar) until it’s fully implemented, so users don’t see a control that appears to do nothing beyond changing the icon state.

```suggestion
        EventHandler.on(controls, "click", ".dropdown-item-presentation", async e => {
            e.preventDefault();

            // If the browser doesn't support the fullscreen API, don't pretend the control works.
            if (!document.fullscreenEnabled) {
                return;
            }

            const item = e.delegateTarget;

            // Toggle fullscreen on the root element for this viewer.
            if (document.fullscreenElement === el) {
                await document.exitFullscreen();
            } else {
                // Some browsers require this to be called from the click handler directly.
                await el.requestFullscreen();
            }
        });

        // Keep the "active" state of the presentation dropdown item in sync with fullscreen state.
        document.addEventListener("fullscreenchange", () => {
            const item = controls.querySelector(".dropdown-item-presentation");
            if (!item) {
                return;
            }

            if (document.fullscreenElement === el) {
                item.classList.add("active");
            } else {
                item.classList.remove("active");
            }
        });
```
</issue_to_address>

### Comment 2
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:220` </location>
<code_context>
        label.innerHTML = `${i + 1}`;
</code_context>

<issue_to_address>
**security (javascript.browser.security.insecure-document-method):** User controlled data in methods like `innerHTML`, `outerHTML` or `document.write` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

### Comment 3
<location> `src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js:220` </location>
<code_context>
        label.innerHTML = `${i + 1}`;
</code_context>

<issue_to_address>
**security (javascript.browser.security.insecure-innerhtml):** User controlled data in a `label.innerHTML` is an anti-pattern that can lead to XSS vulnerabilities

*Source: opengrep*
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown

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 adds localization support to the PdfReader component, enabling internationalization of the UI elements. The implementation follows the established pattern used in other components by injecting IStringLocalizer<PdfReader> and providing English and Chinese locale files. Additionally, it refactors the two-page view toggle logic from C# to JavaScript, adds a new presentation mode feature (currently non-functional), and enhances the thumbnail display with page numbers.

Key Changes

  • Added localization support with English and Chinese locale files for all toolbar buttons and menu items
  • Refactored two-page view toggle from C# method-based to JavaScript event-based handling
  • Added presentation mode UI (feature implementation incomplete)

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
PdfReader.razor.cs Added IStringLocalizer injection, removed OnToggleTwoPagesOneView method, added ShowPresentationMode parameter, updated icon field names
PdfReader.razor Replaced hardcoded UI strings with localized strings using @Localizer, added presentation mode menu item, updated dropdown structure with check/default icons
PdfReader.razor.js Removed setPages and resetTwoPagesOneView functions, moved two-page toggle logic to inline event handler, added presentation mode event handler (commented out)
PdfReader.razor.css Removed .init class styling, added dropdown menu active state styling, enhanced thumbnail layout with labels
Locales/en.json New file with English translations for 11 UI elements
Locales/zh.json New file with Chinese translations for 11 UI elements
BootstrapBlazor.PdfReader.csproj Updated version to 10.0.1, added locale file embedding, changed from PackageReference to ProjectReference (problematic)

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

Comment thread src/components/BootstrapBlazor.PdfReader/Locales/en.json
Comment thread src/components/BootstrapBlazor.PdfReader/PdfReader.razor.js
Comment thread src/components/BootstrapBlazor.PdfReader/PdfReader.razor.cs
@ArgoZhang ArgoZhang merged commit 3499375 into master Nov 27, 2025
2 checks passed
@ArgoZhang ArgoZhang deleted the dev-fs branch November 27, 2025 07:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(PdfReader): support localization

2 participants