Skip to content

Conversation

@ayinloya
Copy link
Collaborator

@ayinloya ayinloya commented Dec 23, 2025

PR Type

Enhancement


Description

  • Add internationalization (i18n) support to eKYC form with translation keys

  • Implement dynamic page translations for form labels, placeholders, and messages

  • Add Arabic locale translations for ID information fields

  • Set document direction based on locale (RTL/LTR support)


File Walkthrough

Relevant files
Enhancement
ekyc.js
Implement translation utilities and dynamic page translation logic

packages/embed/src/js/ekyc.js

  • Import translation utilities (translate, translateHtml, getDirection)
    from localisation module
  • Add applyPageTranslations() function to dynamically translate elements
    with data-i18n attributes
  • Implement translated validation messages with field-specific
    translation keys
  • Set document direction and apply translations after locale
    initialization
+48/-6   
ekyc.html
Add translation attributes to HTML elements for i18n support

packages/embed/src/ekyc.html

  • Add data-i18n attributes to all user-facing text elements (headings,
    labels, buttons)
  • Hide main content initially until translations are loaded
  • Replace hardcoded text with translation keys for form fields and
    messages
+98/-25 
ar-EG.json
Add Arabic translations for ID information form fields     

packages/web-components/locales/ar-EG.json

  • Add Arabic translations for bank selection fields (bank, selectBank,
    searchBank, noBankFound)
  • Add translations for citizenship and date of birth fields
+8/-1     
en-GB.json
Add English translations for ID information form fields   

packages/web-components/locales/en-GB.json

  • Add English translations for bank selection fields (bank, selectBank,
    searchBank, noBankFound)
  • Add translations for citizenship and date of birth fields
+8/-1     


Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • @prfectionist
    Copy link
    Contributor

    prfectionist bot commented Dec 23, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Error Handling Gap

    The applyPageTranslations function catches translation errors but only logs them to console. This could result in untranslated UI elements being displayed to users without any fallback mechanism or user-facing error indication.

    function applyPageTranslations() {
      document.querySelectorAll('[data-i18n]').forEach((el) => {
        const key = el.getAttribute('data-i18n');
        if (key) {
          try {
            el.textContent = translate(key);
          } catch (e) {
            console.error(`Translation failed for key: ${key}`, e);
          }
        }
      });
    }
    Async Race Condition

    The main element is unhidden immediately after applyPageTranslations() completes, but setCurrentLocale() is async. If locale loading fails or takes time, translations may not be applied before the UI becomes visible, showing untranslated content briefly.

    await setCurrentLocale(config.translation?.language || 'en');
    document.documentElement.dir = getDirection();
    applyPageTranslations();
    document.querySelector('main').hidden = false;
    Missing Translation Key

    The fieldTranslationKeys mapping doesn't include all possible form fields. If new fields are added or if there are fields not in this mapping, getTranslatedValidationMessage will fall back to using the raw field name instead of a translated label.

    // Map field names to their translation keys
    const fieldTranslationKeys = {
      id_number: 'pages.idInfo.idNumber',
      first_name: 'pages.idInfo.firstName',
      last_name: 'pages.idInfo.lastName',
      day: 'pages.idInfo.day',
      month: 'pages.idInfo.month',
      year: 'pages.idInfo.year',
      citizenship: 'pages.idInfo.citizenship',
      bank_code: 'pages.idInfo.bank',
    };
    
    function getTranslatedValidationMessage(field) {
      const fieldKey = fieldTranslationKeys[field];
      const fieldLabel = fieldKey ? translate(fieldKey) : field;
      return translateHtml('pages.validation.isRequired', { field: fieldLabel });
    }

    @ayinloya ayinloya changed the title Translate ekyc Localisation ekyc Dec 23, 2025
    Comment on lines +118 to +129
    function applyPageTranslations() {
    document.querySelectorAll('[data-i18n]').forEach((el) => {
    const key = el.getAttribute('data-i18n');
    if (key) {
    try {
    el.textContent = translate(key);
    } catch (e) {
    console.error(`Translation failed for key: ${key}`, e);
    }
    }
    });
    }
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    Suggestion: Using textContent will remove any child HTML elements (like icons or nested spans). This could break UI components that contain both text and HTML. Consider checking if the element has child nodes before replacing content, or use a data attribute to mark text-only elements. [possible issue, importance: 9]

    Suggested change
    function applyPageTranslations() {
    document.querySelectorAll('[data-i18n]').forEach((el) => {
    const key = el.getAttribute('data-i18n');
    if (key) {
    try {
    el.textContent = translate(key);
    } catch (e) {
    console.error(`Translation failed for key: ${key}`, e);
    }
    }
    });
    }
    function applyPageTranslations() {
    document.querySelectorAll('[data-i18n]').forEach((el) => {
    const key = el.getAttribute('data-i18n');
    if (key) {
    try {
    if (el.children.length === 0) {
    el.textContent = translate(key);
    } else {
    const textNodes = Array.from(el.childNodes).filter(node => node.nodeType === Node.TEXT_NODE);
    if (textNodes.length === 1) {
    textNodes[0].textContent = translate(key);
    }
    }
    } catch (e) {
    console.error(`Translation failed for key: ${key}`, e);
    }
    }
    });
    }

    Comment on lines +140 to +143
    await setCurrentLocale(config.translation?.language || 'en');
    document.documentElement.dir = getDirection();
    applyPageTranslations();
    document.querySelector('main').hidden = false;
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    Suggestion: If applyPageTranslations() fails or throws an error, the main element will remain hidden, leaving users with a blank screen. Wrap the translation logic in a try-catch block to ensure the UI is always shown, even if translations fail. [general, importance: 7]

    Suggested change
    await setCurrentLocale(config.translation?.language || 'en');
    document.documentElement.dir = getDirection();
    applyPageTranslations();
    document.querySelector('main').hidden = false;
    await setCurrentLocale(config.translation?.language || 'en');
    document.documentElement.dir = getDirection();
    try {
    applyPageTranslations();
    } catch (e) {
    console.error('Failed to apply page translations', e);
    }
    document.querySelector('main').hidden = false;

    Copy link
    Contributor

    @beaglebets beaglebets left a comment

    Choose a reason for hiding this comment

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

    I'm curious how we're going to handle the bank names themselves.

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    2 participants