Easily load right-to-left (RTL) language PDFs and Office documents and interact with them directly in your browser, without server-side dependencies.
This demo allows you to:
To add Left-to-Right Language capability in WebViewer:
Step 1: Choose your preferred web stack.
Step 2: Add the ES6 JavaScript sample code provided in this guide.
Once you generate your license key, it will automatically be included in your sample code below.
Apryse collects some data regarding your usage of the SDK for product improvement.
The data that Apryse collects include:
For clarity, no other data is collected by the SDK and Apryse has no access to the contents of your documents.
If you wish to continue without data collection, contact us and we will email you a no-tracking trial key for you to get started.
1// ES6 Compliant Syntax
2// Copilot name: GitHub Copilot, version: 1.0.0, model: GPT-4, version: 2024-06, date: 2025-10-21
3// File: showcase-demos/rtl-language-support/index.js
4
5import WebViewer from '@pdftron/webviewer';
6
7function initializeWebViewer() {
8 WebViewer(
9 {
10 path: '/lib',
11 enableFilePicker: true, // Enable file picker to open files. In WebViewer -> menu icon -> Open File.
12 licenseKey: 'YOUR_LICENSE_KEY', // Replace with your license key.
13 },
14 document.getElementById('viewer')
15 ).then((instance) => {
16
17 // Customize the webviewer left panel.
18 UIElements.customizeUI(instance);
19
20 // Listen for language change events.
21 instance.UI.addEventListener('languageChanged', e => {
22 // Log the previous and new language codes to the console.
23 console.log(`Previous language: ${e.detail.prev} -> New language: ${e.detail.next}`);
24 });
25
26 console.log('WebViewer loaded successfully.');
27 }).catch((error) => {
28 console.error('Failed to initialize WebViewer:', error);
29 });
30};
31
32// Function to handle RTL language selection.
33window.SelectRTLLanguage = (instance, rtlLanguage, matchingButton) => {
34 UIElements.supportedRtlLanguages.forEach((lang) => {
35 lang.button.className = 'rtl-button';
36 });
37
38 if (rtlLanguage !== null) {
39 // Set the selected rtl language and load the corresponding document.
40 matchingButton.className = 'rtl-button-selected';
41 UIElements.selectedRtlLanguage = rtlLanguage;
42 instance.UI.setLanguage(UIElements.selectedRtlLanguage.id);
43 instance.UI.loadDocument(UIElements.selectedRtlLanguage.file);
44 } else {
45 // Reset language to English.
46 UIElements.selectedRtlLanguage = null;
47 instance.UI.setLanguage('en');
48 }
49};
50
51// Helper function to load the ui-elements.js script.
52function loadUIElementsScript() {
53 return new Promise((resolve, reject) => {
54 if (window.UIElements) {
55 console.log('UIElements already loaded');
56 resolve();
57 return;
58 }
59 const script = document.createElement('script');
60 script.src = '/showcase-demos/rtl-language-support/ui-elements.js';
61 script.onload = function () {
62 console.log('✅ UIElements script loaded successfully');
63 resolve();
64 };
65 script.onerror = function () {
66 console.error('Failed to load UIElements script');
67 reject(new Error('Failed to load ui-elements.js'));
68 };
69 document.head.appendChild(script);
70 });
71}
72
73// Load UIElements script first, then initialize WebViewer.
74loadUIElementsScript().then(() => {
75 initializeWebViewer();
76}).catch((error) => {
77 console.error('Failed to load UIElements:', error);
78});
1// ES6 Compliant Syntax
2// Copilot name: GitHub Copilot, version: 1.0.0, model: GPT-4, version: 2024-06, date: 2025-10-21
3// File: showcase-demos/rtl-language-support/ui-elements.js
4
5// Class with static UI elements and related functions for the rtl language support demo.
6
7class UIElements {
8
9 // The list of registered panels in the webviewer.
10 static viewerPanels = null;
11
12 // The tab panel, representing the webviewer left panel.
13 static tabPanel = {
14 handle: null,
15 dataElement: 'tabPanel'
16 };
17
18 // The rtl language support sub-panel to be registered.
19 static rtlLanguagePanel = {
20 handle: null,
21 dataElement: 'rtlLanguagePanel',
22 render: null,
23 };
24
25 static apryseFilesUrl = 'https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/';
26
27 // The list of supported rtl languages along with their sample files.
28 static supportedRtlLanguages = [
29 {
30 id: 'ar',
31 name: 'العربية',
32 englishName: 'Arabic',
33 file: `${UIElements.apryseFilesUrl}UDHR-arabic.pdf`,
34 },
35 {
36 id: 'he',
37 name: 'עברית',
38 englishName: 'Hebrew',
39 file: `${UIElements.apryseFilesUrl}UDHR-hebrew.pdf`,
40 },
41 {
42 id: 'fa',
43 name: 'فارسی',
44 englishName: 'Persian',
45 file: `${UIElements.apryseFilesUrl}UDHR-persian.pdf`,
46 },
47 {
48 id: 'ur',
49 name: 'اردو',
50 englishName: 'Urdu',
51 file: `${UIElements.apryseFilesUrl}UDHR-urdu.pdf`,
52 },
53 ];
54
55 // The currently selected rtl language. Default to the first language in the supportedRtlLanguages list.
56 static selectedRtlLanguage = UIElements.supportedRtlLanguages[0];
57
58 // Customize the webviewer left panel.
59 static customizeUI = (instance) => {
60 const { UI } = instance;
61
62 // Set the toolbar group to the Annotations tools.
63 UI.setToolbarGroup('toolbarGroup-Annotate');
64
65 // Close the tab panel (if it's open) for refreshment.
66 UI.closeElements([UIElements.tabPanel.dataElement]);
67
68 // Get the list of registered panels in the webviewer.
69 UIElements.viewerPanels = UI.getPanels();
70
71 // Find the Tab Panel to modify. The rtl language sub-panel will be added to this Tab panel.
72 UIElements.tabPanel.handle = UIElements.viewerPanels.find((panel) => panel.dataElement === UIElements.tabPanel.dataElement);
73
74 // Register the rtl language sub-panel.
75 UIElements.RegisterRtlLanguagePanel(instance);
76
77 // Add the new rtl language sub-panel to list of sub-panels under the Tab Panel.
78 UIElements.rtlLanguagePanel.handle = { render: UIElements.rtlLanguagePanel.dataElement };
79 UIElements.tabPanel.handle.panelsList = [UIElements.rtlLanguagePanel.handle, ...UIElements.tabPanel.handle.panelsList];
80
81 UI.openElements([UIElements.tabPanel.dataElement]);
82 };
83
84 // Register the rtl language sub-panel.
85 static RegisterRtlLanguagePanel = (instance) => {
86 UIElements.rtlLanguagePanel.render = UIElements.createRtlLanguagePanelElements(instance);
87 instance.UI.addPanel({
88 dataElement: UIElements.rtlLanguagePanel.dataElement,
89 location: 'left',
90 icon: '<svg fill="#000000" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24px" height="24px" viewBox="796 796 200 200" enable-background="new 796 796 200 200" xml:space="preserve"><g><path d="M973.166,818.5H818.833c-12.591,0-22.833,10.243-22.833,22.833v109.333c0,12.59,10.243,22.833,22.833,22.833h154.333 c12.59,0,22.834-10.243,22.834-22.833V841.333C996,828.743,985.756,818.5,973.166,818.5z M896,961.5h-77.167 c-5.973,0-10.833-4.859-10.833-10.833V841.333c0-5.974,4.86-10.833,10.833-10.833H896V961.5z M978.58,872.129 c-0.547,9.145-5.668,27.261-20.869,39.845c4.615,1.022,9.629,1.573,14.92,1.573v12c-10.551,0-20.238-1.919-28.469-5.325 c-7.689,3.301-16.969,5.325-28.125,5.325v-12c5.132,0,9.924-0.501,14.366-1.498c-8.412-7.016-13.382-16.311-13.382-26.78h11.999 c0,8.857,5.66,16.517,14.884,21.623c4.641-2.66,8.702-6.112,12.164-10.351c5.628-6.886,8.502-14.521,9.754-20.042h-49.785v-12 h22.297v-11.986h12V864.5h21.055c1.986,0,3.902,0.831,5.258,2.28C977.986,868.199,978.697,870.155,978.58,872.129z"/><g><g><path d="M839.035,914.262l-4.45,11.258h-15.971l26.355-61.09h15.971l25.746,61.09h-16.583l-4.363-11.258H839.035zM852.475,879.876l-8.902,22.604h17.629L852.475,879.876z"/></g></g></g></svg>',
91 title: 'RTL Languages',
92 render: () => UIElements.rtlLanguagePanel.render,
93 });
94 };
95
96 // Create the rtl language panel elements.
97 static createRtlLanguagePanelElements = (instance) => {
98 let panelDiv = document.createElement('div');
99 panelDiv.id = 'rtlLanguagePanel';
100
101 let paragraph = document.createTextNode('Load right to left language PDFs and Office documents and interact with them directly in your browser, without server-side dependencies, thanks to the Apryse Web SDK\'s RTL capabilities.');
102 panelDiv.appendChild(paragraph);
103
104 let dividerDiv = document.createElement('div');
105 dividerDiv.style.borderTop = '1px solid #ccc';
106 dividerDiv.style.margin = '10px 0';
107 panelDiv.appendChild(dividerDiv);
108
109 // Languages division title
110 let languagesTitle = document.createElement("h3");
111 languagesTitle.textContent = "Languages";
112 panelDiv.appendChild(languagesTitle);
113
114 // Create a button for each supported rtl language.
115 UIElements.supportedRtlLanguages.forEach((rtlLanguage) => {
116 let button = UIElements.createButton(instance, rtlLanguage);
117 rtlLanguage.button = button;
118 panelDiv.appendChild(document.createElement("p"));
119 panelDiv.appendChild(button);
120 });
121
122 panelDiv.appendChild(dividerDiv.cloneNode());
123
124 // Create the reset language button.
125 let resetButton = UIElements.createButton(instance);
126 panelDiv.appendChild(document.createElement("p"));
127 panelDiv.appendChild(resetButton);
128
129 // Select the first rtl language by default.
130 UIElements.selectedRtlLanguage.button.click();
131
132 return panelDiv;
133 };
134
135 // Create a button for the given rtl language.
136 // If rtlLanguage is null, create the reset language button.
137 static createButton = (instance, rtlLanguage = null) => {
138 let button = document.createElement("button");
139 button.id = (rtlLanguage === null) ? `resetBtn` : `${rtlLanguage.id}Btn`;
140 button.textContent = (rtlLanguage === null) ? 'Reset Language' : `${rtlLanguage.name} (${rtlLanguage.englishName})`;
141 button.style.width = '100%';
142 button.style.backgroundColor = 'blue';
143 button.style.color = 'white';
144 button.style.border = 'none';
145 button.style.padding = '10px 15px';
146 button.style.borderRadius = '12px';
147 button.onmouseover = () => button.style.opacity = '0.8';
148 button.onmouseout = () => button.style.opacity = '1.0';
149 button.style.cursor = 'pointer';
150 button.onclick = () => window.SelectRTLLanguage(instance, rtlLanguage, button);
151
152 return button;
153 };
154}
1/* RTL Language Support Demo Styles */
2
3.rtl-button {
4 background-color: blue;
5}
6
7.rtl-button-selected {
8 background-color: darkblue;
9}
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales