Globalization Development Kit для PL/SQL: UTL_I18N и UTL_LMS

Globalization Development Kit для PL/SQL: UTL_I18N и UTL_LMS

В Oracle10g впервые появился инструментарий Globalization Development Kit (GDK) для Java и PL/SQL, упрощающий процесс разработки приложений с поддержкой глобализации. Если вы занимаетесь разработкой многоязычного приложения, определение локального контекста каждого пользователя и вывод информации в соответствии с требованиями локального контекста может стать самой сложной задачей программирования, которую вам предстоит решить. Входящие в GDK компоненты PL/SQL разделены на два пакета: UTL_I18N и UTL_LMS.


Оглавление статьи[Показать]


 

Пакет UTL_I18N

Пакет UTL_I18N содержит основную рабочую функциональность GDK. Его подпрограммы перечислены в табл. 1.

Функция GET_LOCAL_LANGUAGES является одной из самых полезных в этом пакете. Зная территорию пользователя, можно дополнительно сократить список значений при помощи функции UTL_I18N. GET_LOCAL_LANGUAGES. Данная возможность замечательно подходит для приложений, в которых администратор должен настраивать конфигурацию для конкретных пользователей. Для демонстрации этой функции будут использоваться следующие данные:

CREATE TABLE user_admin (
   id NUMBER(10) PRIMARY KEY,
   first_name VARCHAR2(10 CHAR),
   last_name VARCHAR2(20 CHAR),
   territory VARCHAR2(30 CHAR),
   language VARCHAR2(30 CHAR))
/

BEGIN
INSERT INTO user_admin
     VALUES (1, 'Stan', 'Smith', 'AMERICA', 'AMERICAN');
INSERT INTO user_admin
     VALUES (2, 'Robert', 'Hammon', NULL, 'SPANISH');
INSERT INTO user_admin
     VALUES (3, 'Anil', 'Venkat', 'INDIA', NULL);
COMMIT;
END:
/

 

Таблица 1. Подпрограммы пакета UTL_I18N

Имя Описание
ESCAPE_REFERENCE Документы HTML и XML не всегда поддерживают те же символы, что и база данных. В таких случаях бывает полезно заменить неподдерживаемые символы служебными комбинациями (escapes). Функция получает входную строку и набор символов документа HTML или XML
GET_COMMON_TIME_ZONES Возвращает список основных часовых поясов. Функция особенно удобна для вывода списка, из которого пользователь выбирает часовой пояс для своего профиля
GET_DEFAULT_CHARSET Возвращает имя набора символов по умолчанию
GET_DEFAULT_ISO_CURRENCY Получает обозначение региона и возвращает соответствующий код валюты
GET_DEFAULT_LINGUISTIC_SORT Возвращает самый распространенный критерий сортировки для заданного языка
GET_LOCAL_LANGUAGES Возвращает локальные языки для заданной территории
GET_LOCAL_LINGUISTIC_SORTS Возвращает список имен критериев сортировки для заданного языка
GET_LOCAL_TERRITORIES Возвращает список территорий для заданного языка
GET_LOCAL_TIMEZONES Возвращает все часовые пояса для заданной территории
GET_TRANSLATION Переводит название языка и/или территории на заданный язык и возвращает результат
MAP_CHARSET  Особенно полезна в приложениях, которые пересылают данные, извлеченные из базы, по электронной почте. Обеспечивает преобразование между набором символов базы данных и набором символов, безопасным для пересылки по электронной почте
MAP_FROM_SHORT_LANGUAGE  Для полученного сокращенного названия языка возвращает полное название языка в Oracle
MAP_LANGUAGE_FROM_ISO  Получает имя локального контекста в стандарте ISO и возвращает название языка Oracle
MAP_LOCALE_TO_ISO  Получает язык и территорию, возвращает имя локального контекста в стандарте ISO
MAP_TERRITORY_FROM_ISO  Получает локальный контекст ISO, возвращает название территории Oracle
MAP_TO_SHORT_LANGUAGE  Функция, обратная по отношению к MAP_FROM_SHORT_LANGUAGE: получает полное название языка Oracle, возвращает короткое название
RAW_TO_CHAR  Перегруженная функция, которая получает тип RAW и возвращает VARCHAR2
RAW_TO_NCHAR  Функция идентична RAW_TO_CHAR, но возвращает значение типа NVARCHAR2
STRING_TO_RAW  Преобразует VARCHAR2 или NVARCHAR2 к заданному набору символов, возвращает значение типа RAW
TRANSLITERATE  Возвращает транслитерацию строки, записанной японской каной
UNESCAPE_REFERENCE  Функция, обратная по отношению к ESCAPE_REFERENCE: распознает служебные комбинации и преобразует их в исходные символы


Территория вводится в таблице USER_ADMIN. Вывод списка языков для пользователя Anil осуществляется следующим анонимным блоком:

DECLARE
   -- Создание массива для результирующего набора языков
   v_array   utl_i18n.string_array;
   -- Создание переменной для хранения данных пользователя
   v_user    user_admin%ROWTYPE;
BEGIN
   -- Заполнение переменной данными пользователя Anil
   SELECT *
     INTO v_user
     FROM user_admin
    WHERE ID = 3;

   -- Получение списка языков для территории
   v_array := utl_i18n.get_local_languages (v_user.territory);
   DBMS_OUTPUT.put (CHR (10));
   DBMS_OUTPUT.put_line ('=======================');
   DBMS_OUTPUT.put_line ('User: ' || v_user.first_name || ' '
                         || v_user.last_name
                        );
   DBMS_OUTPUT.put_line ('Territory: ' || v_user.territory);
   DBMS_OUTPUT.put_line ('=======================');

   -- Перебор элементов массива
   FOR y IN v_array.FIRST .. v_array.LAST
   LOOP
      DBMS_OUTPUT.put_line (v_array (y));
   END LOOP;
END;

Программа возвращает следующий результат:

=======================
User: Anil Venkat
Territory: INDIA
=======================
ASSAMESE
BANGLA
GUJARATI
HINDI
KANNADA
MALAYALAM
MARATHI
ORIYA
PUNJABI
TAMIL
TELUGU

Работать с таким списком намного удобнее, чем с полным списком всех языков. Анало­гичная фильтрация может выполняться и для территорий в том случае, если известен язык. Допустим, у пользователя Robert в данный момент территория не определена, но задан испанский язык (SPANISH). Следующий анонимный блок возвращает список действительных территорий для испанского языка:

DECLARE
   -- Создание массива для результирующего набора территорий
   v_array   utl_i18n.string_array;
   -- Создание переменной для хранения данных пользователя
   v_user    user_admin%ROWTYPE;
BEGIN
   -- Заполнение переменной данными пользователя Robert SELECT *
     INTO v_user
     FROM user_admin
    WHERE ID = 2;

   -- Получение списка территорий для языка
   v_array := utl_i18n.get_local_territories (v_user.LANGUAGE);
   DBMS_OUTPUT.put (CHR (10));
   DBMS_OUTPUT.put_line ('=======================');
   DBMS_OUTPUT.put_line ('User: ' || v_user.first_name || ' '
                         || v_user.last_name
                        );
   DBMS_OUTPUT.put_line ('Language: ' || v_user.LANGUAGE);
   DBMS_OUTPUT.put_line ('=======================');

   -- Перебор элементов массива
   FOR y IN v_array.FIRST .. v_array.LAST
   LOOP
      DBMS_OUTPUT.put_line (v_array (y));
   END LOOP;
END;

 

Результат:

=======================
User: Robert Hammon
Language: SPANISH
=======================
SPAIN
CHILE
COLOMBIA
COSTA RICA
EL SALVADOR
GUATEMALA
MEXICO
NICARAGUA
PANAMA
PERU
PUERTO RICO
VENEZUELA

Зная территорию, можно вывести список языков, действительных часовых поясов и валют; все это значительно упростит настройку конфигурации. Если выбран язык, средства UTL_I18N позволяют получить для него набор символов по умолчанию, лингвистическую сортировку по умолчанию, локальные территории и короткое название языка.

 

Пакет обработки ошибок UTL_LMS

UTL_LMS — второй пакет, входящий в GDK. В него включены две функции для выборки и форматирования сообщений об ошибках:

  •  GET_MESSAGE — возвращает необработанное сообщение об ошибке для заданного языка (иначе говоря, параметры сообщения не включены в возвращаемый текст).
  •  FORMAT_MESSAGE — включает в сообщение дополнительную информацию.

Пример:

DECLARE
   v_bad_bad_variable   PLS_INTEGER;
   v_function_out       PLS_INTEGER;
   v_message            VARCHAR2 (500);
BEGIN
   v_bad_bad_variable := 'x';
EXCEPTION
   WHEN OTHERS
   THEN
      v_function_out :=
                 utl_lms.GET_MESSAGE (06502, 'rdbms', 'ora', NULL, v_message);
      -- Вывод неформатированных и отформатированных сообщений
      DBMS_OUTPUT.put (CHR (10));
      DBMS_OUTPUT.put_line ('Message - Not Formatted');
      DBMS_OUTPUT.put_line ('=======================');
      DBMS_OUTPUT.put_line (v_message);
      DBMS_OUTPUT.put (CHR (10));
      DBMS_OUTPUT.put_line ('Message - Formatted');
      DBMS_OUTPUT.put_line ('===================');
      DBMS_OUTPUT.put_line (utl_lms.format_message (v_message,
                                                    ': The quick brown fox'
                                                   )
                           );
END;

При вызове UTL_LMS.GET_MESSAGE язык не был задан, поэтому сообщение возвращается на языке по умолчанию, определяемом параметром NLS_LANGUAGE.

Message - Not Formatted
=======================
PL/SQL: numeric or value error%s

Message - Formatted
===================
PL/SQL: numeric or value error: The quick brown fox

Так как при вызове UTL_LMS.GET_MESSAGE может передаваться язык, при получении со­общения я просто передаю язык пользователя приложения.

 

Варианты реализации GDK

Функции GDK позволяют выбрать несколько разных вариантов реализации. Если в системе должны поддерживаться только два-три локальных контекста, возможно, реализацию проще всего разделить по контекстам. Скажем, для немецкой системы серверы базы данных и приложений настраиваются для этого локального контекста, а для пользователей из Франции используется совершенно иная среда. Однако чаще требуется реализовать полноценную многоязычную среду, в которой новые контексты могут добавляться без приобретения и настройки отдельного экземпляра системы. Такая реализация потребует дополнительных усилий на начальной стадии, но ею гораздо проще управлять в долгосрочной перспективе.

Метод определения локального контекста пользователя в значительной степени зависит от предполагаемой аудитории и типа разрабатываемого приложения. В следующих подразделах рассматриваются три возможных решения, которые следует принять во внимание при проектировании.

 

Метод 1. Кнопки локальных контекстов

Этот метод часто встречается на веб-страницах в Интернете. Посетите сайт компании, которая ведет бизнес в разных странах; на главной странице часто размещаются кнопки или ссылки для выбора языка:

in English | en Español | en Français | in Italiano

Данное решение идеально подходит для ограниченного набора локальных контекстов. Пользователь выбирает свой язык и денежную единицу простым щелчком на ссылке, а если при выборе будет допущена ошибка — достаточно щелкнуть на кнопке Назад в браузере и исправить проблему.

В этом сценарии либо для каждого локального контекста создаются отдельные страницы и код, либо настройки для текущего сеанса сохраняются в cookie или базе данных, чтобы локализация проходила под контролем базы данных. Чаще всего управление локализацией выполняется на уровне приложения.

 

Метод 2. Администрирование пользователей

Метод 2 отлично подходит для управления настройками локального контекста в приложениях с управляемой пользовательской базой (то есть закрытых, например, для анонимных пользователей Интернета). При небольшом количестве пользователей можно воспользоваться пакетом UTL_I18N для вывода списка доступных часовых поясов, локальных контекстов, языков и территорий, как было показано ранее. Пользователь или администратор просто выбирает настройки, подходящие для пользователя; при каждом входе пользователя приложение читает эти настройки и выполняет соответствующую локализацию.

А если количество пользователей очень велико? Управлять настройками каждого пользователя по отдельности в этом случае нереально. Можно, по примеру проектировщиков базы данных Oracle, организовать систему профилей. Реализуйте в своем приложении возможность создания профиля и настройки локального контекста на уровне профиля, а не на уровне пользователя. При добавлении нового пользователя просто назначьте ему профиль. Тем самым вы избавитесь от многих административных хлопот, особенно если позднее вдруг понадобится внести изменения в конфигурацию. Вместо того чтобы изменять данные всех пользователей, достаточно изменить профиль.

 

Метод 3. Гибридный

Метод 3 сочетает в себе отдельные аспекты методов 1 и 2. Он часто применяется в приложениях интернет-магазинов. Большинство покупателей начинают с просмотра сайта в поисках нужного товара. На этой стадии требовать от них ввода полной информации об их местонахождении преждевременно, но при этом данные должны сортироваться в правильном порядке и выводиться на нужном языке, с правильным форматом денежных величин. Чтобы обеспечить правильность базовой информации локального контекста, предложите решение, описанное в методе 1.

А когда покупатель примет решение о покупке, вы требуете, чтобы он ввел профильные данные с информацией о локальном контексте. Локализация становится более конкретной, в ней используются точная дата/время и финансовая информация из базы данных.

Вас заинтересует / Intresting for you:

Управление приложениями PL/SQL...
Управление приложениями PL/SQL... 4651 просмотров Stas Belkov Thu, 16 Jul 2020, 06:20:48
Встроенные методы коллекций PL...
Встроенные методы коллекций PL... 14838 просмотров sepia Tue, 29 Oct 2019, 09:54:01
Тип данных RAW в PL/SQL
Тип данных RAW в PL/SQL 12331 просмотров Doctor Thu, 12 Jul 2018, 08:41:33
Символьные функции и аргументы...
Символьные функции и аргументы... 18586 просмотров Анатолий Wed, 23 May 2018, 18:54:01
Войдите чтобы комментировать

ildergun аватар
ildergun ответил в теме #9549 4 года 5 мес. назад
Да, статейка хорошо!
apv аватар
apv ответил в теме #9546 4 года 5 мес. назад
Крутейшая стать. Ценнейшая информация!))