> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/get-started/samples/showcase-demo-language-switcher.md).

# Language Switcher Showcase Demo Code Sample

Add language localization capabilities to the viewer by switching currently supported languages or adding your own.  Follows the Language Switcher demo found in Showcase.

{% hint style="info" %}
**Requirements**

*These packages are required to use these features in production. Trial keys have unlimited access to all features*

<a href="/web/get-started/readme.md" class="button primary">Web SDK</a><a href="https://showcase.apryse.com/language-switcher" class="button primary">Live demo</a>
{% endhint %}

Add language localization capabilities to the viewer by switching currently supported languages or adding your own.

This demo allows you to:

* Define localized language
* Use a pre-defined language collection on a custom ribbon
* Update toolbar language

### **Implementation steps**

To add language localization to WebViewer UI: Step 1: [Get started with WebViewer](/web/get-started/readme.md) in 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-license-key/apryse-license-key platform="WEB\_VIEWER" variant="compact" %}

{% tabs %}
{% tab title="index.js" %}

<pre class="language-js" data-line-numbers><code class="lang-js">// ES6 Compliant Syntax
// GitHub Copilot (VS Code Extension) - GPT-4 model - July 29, 2025
// File name: index.js

import WebViewer from '@pdftron/webviewer';

const licenseKey = '<code class="expression">visitor.claims.wvKey || "YOUR_WEBVIEWER_LICENSE_KEY"</code>';

function initializeWebViewer() {
  WebViewer(
    {
      path: '/lib',
      initialDoc: 'https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/WebviewerDemoDoc.pdf',
      enableFilePicker: true, // Enable file picker to open files. In WebViewer -> menu icon -> Open File
      licenseKey: licenseKey, // Replace with your license key
    },
    document.getElementById('viewer')
  ).then((instance) => {
    // Default to the first language in the languages list (English).
    UIElements.selectedLanguage = UIElements.languages[0];

    // Customize the webviewer left panel
    UIElements.customizeUI(instance);

    instance.UI.openElements(['MainMenuFlyout']);

    // Listen for language change events
    instance.UI.addEventListener('languageChanged', e => {
      instance.UI.openElements(['MainMenuFlyout']);
      // Log the previous and new language codes to the console
      // console.log(e.detail.prev);
      // console.log(e.detail.next);
    });

    console.log('WebViewer loaded successfully.');
  }).catch((error) => {
    console.error('Failed to initialize WebViewer:', error);
  });
};

// Function to handle language selection
window.SelectLanguage = (instance, language, matchingButton) => {
  UIElements.languages.forEach((lang) => lang.button.style.backgroundColor = 'blue');

  // Set the selected language and load the corresponding document
  matchingButton.style.backgroundColor = 'darkblue';
  UIElements.selectedLanguage = language;
  instance.UI.setLanguage(UIElements.selectedLanguage.id);
};

//helper function to load the ui-elements.js script
function loadUIElementsScript() {
  return new Promise((resolve, reject) => {
    if (window.UIElements) {
      console.log('UIElements already loaded');
      resolve();
      return;
    }
    const script = document.createElement('script');
    script.src = '/showcase-demos/language-switcher/ui-elements.js';
    script.onload = function () {
      console.log('✅ UIElements script loaded successfully');
      resolve();
    };
    script.onerror = function () {
      console.error('Failed to load UIElements script');
      reject(new Error('Failed to load ui-elements.js'));
    };
    document.head.appendChild(script);
  });
}

// Load UIElements script first, then initialize WebViewer
loadUIElementsScript().then(() => {
  initializeWebViewer();
}).catch((error) => {
  console.error('Failed to load UIElements:', error);
});
</code></pre>

{% endtab %}

{% tab title="ui-elements.js" %}
{% code title="ui-elements.js" lineNumbers="true" %}

```js
// ES6 Compliant Syntax
// Copilot name: GitHub Copilot, version: 1.0.0, model: GPT-4, version: 2024-06, date: 2025-10-23
// File: showcase-demos/language-switcher/ui-elements.js

// Class with static UI elements and related functions for the language switcher demo

class UIElements {

    // The list of registered panels in the webviewer
    static viewerPanels = null;

    // The tab panel, representing the webviewer left panel
    static tabPanel = {
        handle: null,
        dataElement: 'tabPanel'
    };

    // The language support sub-panel to be registered
    static languagePanel = {
        handle: null,
        dataElement: 'languagePanel',
        render: null,
    };

    static languages = [
        {
            name: 'English',
            id: 'en',
            englishName: 'English',
        },
        {
            name: 'Français',
            id: 'fr',
            englishName: 'French',
        },
        {
            name: '简体中文',
            id: 'zh_cn',
            englishName: 'Simplified Chinese',
        },
        {
            name: '繁體中文',
            id: 'zh_tw',
            englishName: 'Traditional Chinese',
        },
        {
            name: 'Deutsch',
            id: 'de',
            englishName: 'German',
        },
        {
            name: 'Nederlands',
            id: 'nl',
            englishName: 'Dutch',
        },
        {
            name: 'Pусский',
            id: 'ru',
            englishName: 'Russian',
        },
        {
            name: 'Español',
            id: 'es',
            englishName: 'Spanish',
        },
        {
            name: 'Italiano',
            id: 'it',
            englishName: 'Italian',
        },
        {
            name: '日本語',
            id: 'ja',
            englishName: 'Japanese',
        },
        {
            name: '한국어',
            id: 'ko',
            englishName: 'Korean',
        },
        {
            name: 'Português',
            id: 'pt_br',
            englishName: 'Portuguese',
        },
        {
            name: 'česky, čeština',
            id: 'cs',
            englishName: 'Czech',
        },
        {
            name: 'Ελληνικά',
            id: 'el',
            englishName: 'Greek',
        },
        {
            name: 'Magyar',
            id: 'hu',
            englishName: 'Hungarian',
        },
        {
            name: 'Polski',
            id: 'pl',
            englishName: 'Polish',
        },
        {
            name: 'українська',
            id: 'uk',
            englishName: 'Ukrainian',
        },
        {
            name: 'Romanian',
            id: 'ro',
            englishName: 'Romanian',
        },
        {
            name: 'Svenska',
            id: 'sv',
            englishName: 'Swedish',
        },
        {
            name: 'Türk',
            id: 'tr',
            englishName: 'Turkish',
        },
        {
            name: 'ไทย',
            id: 'th',
            englishName: 'Thai',
        },
        {
            name: 'Tiếng Việt',
            id: 'vi',
            englishName: 'Vietnamese',
        },
        {
            name: 'Bahasa Indonesia',
            id: 'id',
            englishName: 'Indonesian',
        },
        {
            name: 'Melayu',
            id: 'ms',
            englishName: 'Malay',
        },
        {
            name: 'हिन्दी',
            id: 'hi',
            englishName: 'Hindi',
        },
        {
            name: 'বাংলা',
            id: 'bn',
            englishName: 'Bengali',
        },
        {
            name: 'العربية',
            id: 'ar',
            englishName: 'Arabic',
        },
        {
            name: 'עברית',
            id: 'he',
            englishName: 'Hebrew',
        },
        {
            name: 'فارسی',
            id: 'fa',
            englishName: 'Persian',
        },
        {
            name: 'اردو',
            id: 'ur',
            englishName: 'Urdu',
        },
    ];

    // The currently selected language.
    static selectedLanguage = null;

    // Customize the webviewer left panel
    static customizeUI = (instance) => {
        const { UI } = instance;

        // Set the toolbar group to the Annotations tools
        UI.setToolbarGroup('toolbarGroup-Annotate');

        // Close the tab panel (if it's open) for refreshment.
        UI.closeElements([UIElements.tabPanel.dataElement]);

        // Get the list of registered panels in the webviewer
        UIElements.viewerPanels = UI.getPanels();

        // Find the Tab Panel to modify. The language sub-panel will be added to this Tab panel.
        UIElements.tabPanel.handle = UIElements.viewerPanels.find((panel) => panel.dataElement === UIElements.tabPanel.dataElement);

        // Register the language sub-panel
        UIElements.RegisterLanguagePanel(instance);

        // Add the new language sub-panel to list of sub-panels under the Tab Panel
        UIElements.languagePanel.handle = { render: UIElements.languagePanel.dataElement };
        UIElements.tabPanel.handle.panelsList = [UIElements.languagePanel.handle, ...UIElements.tabPanel.handle.panelsList];

        UI.openElements([UIElements.tabPanel.dataElement]);
    };

    // Register the language sub-panel
    static RegisterLanguagePanel = (instance) => {
        UIElements.languagePanel.render = UIElements.createLanguagePanelElements(instance);
        instance.UI.addPanel({
            dataElement: UIElements.languagePanel.dataElement,
            location: 'left',
            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>',
            title: 'Languages',
            render: () => UIElements.languagePanel.render,
        });
    };

    // Create the language panel elements.
    static createLanguagePanelElements = (instance) => {
        let panelDiv = document.createElement('div');
        panelDiv.id = 'languagePanel';

        let paragraph = document.createTextNode('Utilize WebViewer\'s localization capabilities by switching between currently supported languages, or easily adding your own!');
        panelDiv.appendChild(paragraph);

        let dividerDiv = document.createElement('div');
        dividerDiv.style.borderTop = '1px solid #ccc';
        dividerDiv.style.margin = '10px 0';
        panelDiv.appendChild(dividerDiv);

        // Languages division title
        let languagesTitle = document.createElement("h3");
        languagesTitle.textContent = "Languages";
        panelDiv.appendChild(languagesTitle);

        // Create a button for each supported language
        UIElements.languages.forEach((language) => {
            let button = UIElements.createButton(instance, language);
            language.button = button;
            panelDiv.appendChild(document.createElement("p"));
            panelDiv.appendChild(button);
        });

        panelDiv.appendChild(dividerDiv.cloneNode());

        // Select the first language by default
        UIElements.selectedLanguage.button.click();

        return panelDiv;
    };

    // Create a button for the given language.
    static createButton = (instance, language) => {
        let button = document.createElement("button");
        button.id = `${language.id}Btn`;
        button.textContent = `${language.name} (${language.englishName})`;
        button.style.width = '100%';
        button.style.backgroundColor = 'blue';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.padding = '10px 15px';
        button.style.borderRadius = '12px';
        button.onmouseover = () => button.style.opacity = '0.8';
        button.onmouseout = () => button.style.opacity = '1.0';
        button.style.cursor = 'pointer';
        button.onclick = () => window.SelectLanguage(instance, language, button);

        return button;
    };
}
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/get-started/samples/showcase-demo-language-switcher.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
