You can use pipelined wrapper for example (original function returns package-defined collection type):
SQL> create type t_lang_tab is table of varchar2(4000)
2 /
SQL> create or replace function get_language(
2 p_value in varchar2
3 ) return t_lang_tab
4 pipelined
5 is
6 res utl_i18n.string_array;
7 begin
8 res := utl_i18n.GET_LOCAL_LANGUAGES(p_value);
9 if res is not null then
10 for i in 1..res.count loop
11 pipe row (substr(res(i),1,4000));
12 end loop;
13 end if;
14 return;
15 end;
16 /
SQL> col column_value format a25
SQL> col value format a25
SQL> select t.column_value, p.value
2 from v$nls_valid_values p,
3 table(get_language(p.value)) t
4 where parameter = 'TERRITORY'
5 /
COLUMN_VALUE VALUE
------------------------- -------------------------
ENGLISH AMERICA
GERMAN DIN GERMANY
CANADIAN FRENCH CANADA
FRENCH CANADA
CATALAN SPAIN
SWEDISH FINLAND
PORTUGUESE BRAZIL
LATIN AMERICAN SPANISH MEXICO
SPANISH MEXICO
SPANISH CATALONIA
ARABIC EGYPT
....
If you want to create language table you can do this:
SQL> CREATE TABLE languages (
2 country VARCHAR2(30) NOT NULL,
3 language VARCHAR2(30) NOT NULL,
4 CONSTRAINT languages_pk PRIMARY KEY (country, language)
5 )
6 /
Primary key should be composite because there are multi-lingual countries like Canada. Now you can use above function to fill table:
SQL> INSERT INTO languages
2 select p.value, t.column_value
3 from v$nls_valid_values p,
4 table(get_language(p.value)) t
5 where parameter = 'TERRITORY'
6 order by 1
7 /
SQL> commit;
SQL> select * from languages;
COUNTRY LANGUAGE
------------------------------ ------------------------------
AMERICA ENGLISH
ARGENTINA SPANISH
BELARUS RUSSIAN
BELGIUM FRENCH
BRAZIL PORTUGUESE
CANADA FRENCH
CANADA CANADIAN FRENCH
CATALONIA SPANISH
CHILE SPANISH
COLOMBIA SPANISH
...