Mastering Multi-Language Applications in Oracle APEX

Mastering Multi-Language Applications in Oracle APEX

Essential Configuration for Robust Internationalization

Oracle APEX provides powerful built-in capabilities for developing multi-lingual applications, enabling developers to deliver localized user experiences with minimal overhead. When properly configured, APEX allows applications to dynamically adapt language, labels, messages, and text based on user preferences or session context.

Supporting multiple languages is essential for modern applications, especially in enterprise and global environments. A robust internationalization strategy improves usability, accessibility, and adoption across diverse user bases.

This article presents a recommended and production-ready approach for setting and managing session language in multi-lingual Oracle APEX applications. We focus on session-based language handling, user preferences, and best practices inspired by community knowledge and real-world implementations.

We will walk through:

  • Required globalization settings
  • Session language initialization logic
  • Authentication handling
  • User-driven language selection
  • Language repository configuration in Oracle APEX

1. Multi-Language Support in Oracle APEX

Oracle APEX supports multi-language applications through a combination of:

  • Application globalization settings
  • Translatable text repositories
  • Session language context
  • User preferences

Key goals of a proper multi-language setup include:

  • Consistent language selection across sessions
  • Automatic language initialization after login
  • Allowing users to explicitly choose their preferred language
  • Ensuring all UI text is resolved dynamically

A session-based language strategy is generally preferred, as it provides flexibility and clean separation between users sharing the same application.

2. Translation Utility Package (Required Helper)

To keep the implementation clean and reusable, we centralize all language decision logic (browser language, user preference, explicit override) in a small PL/SQL helper package: ait_translate_util, originally developed by Hayden Hudson.

How it relates to the steps below
This package is the engine used by the application processes/branches described in:

  • Step 2 (Public Page Reload Branch): initializes the session language on first contact
  • Step 3 (After Authentication Process): re-initializes correctly right after login
  • Step 4 (User Language Selector): applies the user’s selection and stores preference

Install this package in the same schema that runs your APEX app, before configuring the processes/branches.

(The full code is in Annex A at the end of the article.)

3. Core Configuration Steps for Session-Based Language Handling

— Source: Based on the "translate-apex" open-source project by Hayden Hudson

3.1 Step 1 – Globalization Settings

Navigate to Application Properties → Globalization and configure:

  • Application Language Derived From → Session
     

This setting instructs APEX to resolve translations dynamically from the current session language rather than a fixed application language.

This is a mandatory step for dynamic multi-language behavior.

3.2 Step 2 – Public Page Reload Branch (Initialize early)

On public (non-authenticated) pages, create a Before Header branch that redirects the page to itself only when the session language has not yet been set.

Branch PL/SQL Condition

declare

    l_retval boolean := false;

begin

    if apex_util.get_session_lang is null then

        ait_translate_util.set_session_lang(p_application_id => :APP_ID);

        l_retval := true;

    end if;

    return l_retval;

end;

Purpose

  • Ensures the session language is initialized as early as possible
  • Prevents untranslated UI elements on first page load
  • Avoids unnecessary redirects once the language is set

Note: This is where your app first uses the ait_translate_util package to decide the initial language.

3.3 Step 3 – After Authentication Process (Re-initialize after login)

Create an After Authentication process at the application level:

begin

    ait_translate_util.set_session_lang(p_application_id => :APP_ID);

end;

Why this matters

  • Ensures the language is properly re-initialized after login
  • Allows language to be derived from:
    • User preferences
    • Browser language
    • Application defaults
  • Guarantees a consistent experience for authenticated users

At this point, the same helper decides the final language again, but now with the context of an authenticated user.

3.4 Step 4 – Allowing Users to Set Their Language Preference

To empower users, provide a language selector (e.g., a radio group or select list) on Page 0 (Global Page).

Create a page process that executes:

ait_translate_util.set_session_lang(

    p_application_id => :APP_ID,

    p_language       => :P0_LANG

);

Recommended UI Pattern

  • Radio List or Select List
  • Display language names (e.g., English, Spanish, Portuguese)
  • Store language codes (en, es, pt)

This ensures:

  • Immediate language switching
  • Persistent session-level preference
  • User control over localization

4. Configuring the Oracle APEX Language Repository (Critical Step)

For multi-language support to function correctly, the APEX language repository must be configured and populated.

4.1 Enabling Languages

Navigate to:

Shared Components → Globalization → Translate Application

Here you must:

  • Add the target languages (e.g., es, pt, fr)
  • Generate the translation repository
     

4.2 Translating Text

APEX supports translation of:

  • Page titles
  • Labels
  • Button text
  • Messages
  • Report column headings
  • LOV display values

Translations can be:

  • Entered manually via the APEX UI
  • Imported/exported using XLIFF files
  • Managed through automated scripts for large applications
     

⚠️ Without configuring the language repository, session language changes will occur, but no text will actually be translated.

Implementing multi-language support in Oracle APEX goes far beyond enabling a single setting. A well-designed internationalization strategy requires careful handling of session context, authentication flow, user preferences, and translation repositories.

By combining:

  • Session-derived language configuration
  • A centralized translation utility package (ait_translate_util)
  • Proper initialization logic
  • User-controlled language selection
  • Correctly configured APEX translation repositories

developers can deliver truly global APEX applications with a seamless and professional user experience.

 

March 22th, 2026

Author: Samir Chavez
 

WAYKITECH “We Make Technology Work for You”

 

 

Annex A — PL/SQL Helper Package ait_translate_util

— Source: Based on the "translate-apex" open-source project by Hayden Hudson

What this package does (quick summary)

  • Detects browser language (HTTP_ACCEPT_LANGUAGE)
  • Validates/matches it against the application’s translated languages
  • Applies a priority order:
     

    1. Explicit language passed by UI selector (p_language)
    2. Stored user preference (FSP_LANGUAGE_PREFERENCE)
    3. Browser language (mapped to available translations)
    4. App primary language (fallback)
       
  • Sets the session language via apex_util.set_session_lang
  • Persists preference only for authenticated users
  • Clears “mistaken” preference when user is nobody (public)
     

Package specification

create or replace package ait_translate_util as

    procedure set_session_lang(p_application_id in number default v('APP_ID'),

                               p_language       in varchar2 default null);

end ait_translate_util;

/

Package body

create or replace package body ait_translate_util as

 

  gc_scope_prefix constant varchar2(31) := lower($$plsql_unit) || '.';

 

  function get_browser_language (

    p_application_id in number default v('APP_ID')

  )

  return varchar2

  is

    l_browser_language       varchar2(4000);

    l_final_browser_language varchar2(5);

  begin

    select lower(column_value)

    into l_browser_language

    from table(

           apex_string.split(

             owa_util.get_cgi_env('HTTP_ACCEPT_LANGUAGE'),

             ','

           )

         )

    fetch first 1 rows only;

 

    select coalesce(

             l1.exact_match,

             l2.like_match,

             l3.like_match,

             aaa.application_primary_language

           )

    into l_final_browser_language

    from dual

    left join (

      select translated_app_language exact_match

      from apex_application_trans_map

      where primary_application_id = p_application_id

        and translated_app_language = l_browser_language

    ) l1 on 1 = 1

    left join (

      select translated_app_language like_match

      from apex_application_trans_map

      where primary_application_id = p_application_id

        and translated_app_language like '%' || l_browser_language || '%'

      fetch first 1 rows only

    ) l2 on 1 = 1

    left join (

      select translated_app_language like_match

      from apex_application_trans_map

      where primary_application_id = p_application_id

        and l_browser_language like '%' || translated_app_language || '%'

      fetch first 1 rows only

    ) l3 on 1 = 1

    left join apex_applications aaa

      on aaa.application_id = p_application_id;

 

    return l_final_browser_language;

 

  exception

    when others then

      raise;

  end get_browser_language;

 

  procedure set_session_lang(

    p_application_id in number default v('APP_ID'),

    p_language       in varchar2 default null

  )

  as

    l_preference_language varchar2(5)

      := apex_util.get_preference('FSP_LANGUAGE_PREFERENCE');

    l_final_language varchar2(5);

 

    procedure clear_mistaken_public_preference is

    begin

      if v('APP_USER') = 'nobody'

         and l_preference_language is not null

      then

        apex_util.set_preference(

          p_preference => 'FSP_LANGUAGE_PREFERENCE',

          p_value      => null

        );

        l_preference_language := null;

      end if;

    end clear_mistaken_public_preference;

 

  begin

    clear_mistaken_public_preference;

 

    l_final_language :=

      case

        when p_language is not null

          then p_language

        when l_preference_language is not null

          then l_preference_language

        else get_browser_language(p_application_id)

      end;

 

    apex_util.set_session_lang(p_lang => l_final_language);

 

    if v('APP_USER') != 'nobody'

       and p_language is not null

    then

      apex_util.set_preference(

        p_preference => 'FSP_LANGUAGE_PREFERENCE',

        p_value      => p_language

      );

    end if;

 

  exception

    when others then

      raise;

  end set_session_lang;

 

end ait_translate_util;

/