Is there an easy way to convert HTTP_ACCEPT_LANGUAGE to Oracle NLS_LANG settings?
When adding internationalization capabilities to an Oracle web application (based on mod_plsql) I would like to interpret the HTTP_ACCEPT_LANGUAGE parameter and use it to set various NLS_ * parameters in the Oracle session.
For instance:
HTTP_ACCEPT_LANGUAGE=de
alter session set nls_territory=germany;
alter session set nls_lang=...
However, you can end up with something more complicated, I suppose ...
HTTP_ACCEPT_LANGUAGE=en-us,en;q=0.5
How did people do this before?
EDIT - after Kurt's detailed answer
Thanks for the clear and detailed answer Kurt. I didn't really get it though, as I was really asking if there are any existing Oracle widgets that handled this.
I'm already going through the manual parsing of the HTTP_ACCEPT_LANGUAGE variable and as Kurt pointed out in his answer, there are several subtle areas of complexity. It's like something that should have been done many times before. As I wrote more and more code, I had the experience of being immersed in the feeling "I am reinventing the wheel". :)
There must be an existing Oracle approach to do this - maybe something in the iAS ??
EDIT - came across an answer
While looking for something else, I came across a UTL_I18N package that does exactly what I want:
Is there an easy way to convert HTTP_ACCEPT_LANGUAGE to Oracle NLS_LANG settings?
a source to share
Finally came across an answer. Oracle UTL_I18N package contains functions to map browser language codes to Oracle NLS settings:
utl_i18n.map_language_from_iso;
utl_i18n.map_territory_from_iso;
The mapping doesn't seem to handle multilingual settings very well, for example. en-us, en; q = 0.5, but as long as you only use the first 5 characters the functions seem to work fine.
HTTP_ACCEPT_LANGUAGE: ar-lb,en-gb;q=0.5
v_language:
v_territory:
HTTP_ACCEPT_LANGUAGE: ar-lb
v_language: ARABIC
v_territory: LEBANON
a source to share
Of course, this is not too difficult if you divide the problem correctly and don't get ambitious at first.
You essentially need two functions, one to parse HTTP_ACCEPT_LANGUAGE
and generate language code, and the other to generate the appropriate commands set
.
The former can get pretty tricky; if you are only given "en" you probably want to create "en-us", you have to deal with multiple choices, when nothing is perfect, you have to deal with invalid header values, and so on. Don't try to figure it out all at once: do something very simple first and continue later.
The same is more or less suitable for the other half when generating commands set
, but it's still simple and in and of itself; it is really just a search function, although it can be a little more complex depending on what is presented to it.
What will really make or break your coding experience with something like this is your unit tests. This is an ideal problem for unit testing and test-driven development. Unit tests ensure that when you change the situation, the old functionality keeps working and makes it easier to add new features and fix bugs because you just add another test and you have that to guide you from now on. (You will also find it easier to do a complete overhaul of one of the features if you find that at some point you are wrong, because you can easily confirm that the new version does not break anything.)
How you unit test in your environment is probably a bit outside the scope of this question, but let me add some advice. First, if there is a unit test framework ("pl-sql-unit?") Available for your environment, that's great. If not, don't panic. You don't need anything complicated: just a bunch of inputs and expected outputs, and a way to run them through a function and either say "it's okay!" or show incorrect results. You can probably write one, simple PL / SQL function that reads the inputs and expected outputs from the table and does it for you.
a source to share