Oracle APEX - apex_lang.message vs apex_lang.lang

Oracle APEX - apex_lang.message vs apex_lang.lang

Similarities. Differences. Pros. Cons. You know..."vs."

This is a complicated subject because apex_lang.message (message) and apex_lang.lang (lang) are very similar and yet the differences are meaningful. Both message and lang allow you to do substitutions into the string and translate the string to another language. The devil, as they say, is in the details. Deciding when to use one or the other is complicated.

TLDR

If you are translating your application to another language, use message.

If you want to store all of your translations (or substitutions) in a single application and use them in other applications, use message.

If you want to create translations dynamically (using an API) use message.

NOTE: message requires you to register a message in order to do substitutions or translations.

If none of the above apply, you just want to do substitutions, and you don't plan to translate to another language, use lang. (Yes, despite the name, lang should only be used for substitutions, not translations. And yes...lang can do translations, but message is just the better choice.)

Note: lang does not require you to register a dynamic translation to do substitutions, but it does require a dynamic translation to do translations. lang is case sensitive.

The Details

The easiest way to show how each behaves is to show a few examples. These examples assume I have 2 APEX applications (app 111 and app 222). Both applications have two languages, English and Spanish. App 111 has translations defined for both message and lang. App 222 does not have any translations defined.

apex_lang.message

App 111 has the following "Text Messages" defined in Shared Components > Translate > Text Messages:

NameEnglish (en)Spanish (es)
GREETINGHelloHola
APPROVED%0 approved expense report number %1.%0 aprobó el informe de gastos número %1.

Let's look at the results you get for certain input bind variables. Assume we have a classic report with the following query:

select apex_lang.message(p_name           => :P1_NAME,
                         p0               => :P1_PARAM0,
                         p1               => :P1_PARAM1,
                         p_lang           => :P1_LANG,
                         p_application_id => :P1_APP_ID) the_result
  from dual

If :P1_LANG is null, apex_lang.message assumes the current application language.

If :P1_APP_ID is null, apex_lang.message assumes the current application id (:APP_ID).

Sorry, you have to scroll left and right on the table below. I haven't figured out how to improve the format of this blog yet.

The application you are runningApplication LanguageP1_NAMEP1_PARAM0P1_PARAM1P1_LANGP1_APP_IDthe_resultNotes about this result
111enGREETINGany valueany valueHello
111esGREETINGany valueany valueHola
111engreetingany valueany valueHellop_name always converts to upper case in order to find the message.
111engrEeTingany valueany valueHolap_name always converts to upper case in order to find the message.
111enGREETINGany valueany valueesHolabecause we specified the language, it did the translation
222engrEEtingany valueany valueAPEX Version Dependent: Greeting (v22.1), grEEting (v19.2), GREETING (other versions)because app 222 does not have messages defined, message converts to upper case, and can't find a value, so it returns "Greeting" in some manner, case depending on version.
222engreETingany valueany valuees111HolaBecause we provided both p_lang and p_application_id, message was able to find the translation in app 11 and convert to Spanish.
111enapprovedVelimir17Velimir approved expense report number 17.
111esAPPROVEDVelimir17Velimir aprobó el informe de gastos número 17.
222enApprovedVelimir17ApprovedCase depends on APEX Version
111 or 222en%0 Approved expense report number %1Velimir17%0 APPROVED EXPENSE REPORT NUMBER %1message will not do substitutions if the string has not been registered.

apex_lang.lang

App 111 has the following "Dynamic Translations" defined in Shared Components > Translate > Dynamic Translations:

Translation FromLanguageTranslate To
HelloesHola
%0 approved expense report number %1.es%0 aprobó el informe de gastos número %1.

Let's look at the results you get for certain input bind variables. Assume we have a classic report with the following query:

select apex_lang.lang(p_primary_text_string    => :P1_NAME,
                      p0                       => :P1_PARAM0,
                      p1                       => :P1_PARAM1,
                      p_primary_language       => :P1_LANG) the_result
  from dual

If :P1_LANG is null, apex_lang.lang assumes the current application language.

apex_lang.lang does not have the ability to look for a Dynamic Translation in another application. It must be in the current application.

Sorry, you have to scroll left and right on the table below. I haven't figured out how to improve the format of this blog yet.

The application you are runningApplication Session LanguageP1_NAMEP1_PARAM0P1_PARAM1P1_LANGthe_resultNotes about this result
111enHelloany valueany valueHello
111esHelloany valueany valueHola
111enhelloany valueany valuehellohello, lower case, is not registered.
222esHelloany valueany valueHelloHello, is not registered in app 222 and will not translate.
111en%0 approved expense report number %1.Velimir17Velimir approved expense report number 17.
111es%0 approved expense report number %1.Velimir17Velimir aprobó el informe de gastos número 17.
111en%0 approved expense report number %1.Velimir17esVelimir aprobó el informe de gastos número 17.because we specified the language it translated.
111es%0 Approved expense report number %1.Velimir17Velimir Approved expense report number 17.apex_lang.lang is case sensitive. Because "Approved" has a capital A it did not translate.
222en%0 approved expense report number %1.Velimer17Velimir approved expense report number 17.apex_lang.lang does not require a registration to do subsitutions.
222es%0 approved expense report number %1.Velimer17Velimir approved expense report number 17.apex_lang.lang does not require a registration to do subsitutions, but it will not translate without a registered translation.
111 or 222enHi %0, have a great %1.MichaeldayHi Michael, have a great day.apex_lang.lang does not require a registration to do substitutions.