Falcon Space. Локализация

Введение

Локализация используется на 2 уровнях:

  • Интерфейс - перевод надписей интерфейса программы (например, универсальные постоянные надписи, названия кнопок, сообщения в компонентах, которые хранятся не в базе, а в файлах ресурсах JS).
  • Данные - бизнес-данные по проекту (товары, категории, страницы). Перевод делается для данных в таблицах БД (то, что хранится в таблицах в виде строк).

Чтобы включить/выключить режим работы языков, необходимо в процедуре as_getLayoutInfo установить параметр enableLang = 1. 

Локализация интерфейса

Для локализации интерфейса используются метки из таблицы as_langText

Примечание.

  1. Используйте partCode для объединения меток в группу (это оптимизирует кеширование меток). Для наиболее распространенных меток оставляйте partCode пустым. Хороший способ простановки - в зависимости от кода страницы в виде pg{Code}, напр. pgCatalog
  2. В базе данных дополнительных манипуляций для извлечения делать не требуется.
  3. В интерфейсе используем метки через HTML helper Lang
  4. В JS файлах используем словарь из /js/as/controls/localization/resource{lang}.js

Локализация данных

Для локализации некой таблицы (в примере as_menu) используются дополнительные таблицы. Для каждой подобной таблицы создается своя таблица данных с именем as_lang_{tableName}.

tableName - это название соответствующей таблицы для которой мы хотим внедрить локализацию (она содержит строковые столбцы-аналоги первичной таблицы, строки в ней имеют значения для разных языков для этих полей)

Пример:

 

  • Поля name, title - это поля таблицы as_menu, которые нам надо перевести (т.е. может быть любое количество полей).
  • Поле itemID - это идентификатор в основной таблице (as_menu).

В запросе бизнес-логики указываем примерно такой код (ожидаем что на входе в процедуру пришел @langID int):

ALTER PROCEDURE procedure [dbo].[as_getMenu]
 @roles nvarchar(256),
 @langID int = 0
AS
BEGIN
     select m.id,
		   isnull(lm.name, m.name) as name,
		   m.url,
		   m.pattern,
		   m.parentID,
		   isnull(lm.title,m.title) as title,
		   m.preTitle,
		   m.cssclass,
		   m.ord
	  from as_menu m
	  left join as_lang_menu lm on lm.itemID = m.id  and langID = @langID
	  where   [dbo].[sec_hasAccessByUsersRoles]  (@username, '', m.roles) = '1'
		and (@username<>''  and isnull(isNotAuthMenu, '0')='0' or @username=''
                and isNotAuthMenu='1')

Обратите внимание, как извлекаем значение текстового поля (через isnull - берем либо языковое поле, либо если его нет, то поле по умолчанию и основной таблицы)

Также обратите внимание, что делаем left join с таблицей as_lang_{tableName} по 2 условиям (langID и itemID).

Очень рекомендуется придерживаться этой схемы локализации - это упростит в дальнейшем сопровождение проекта. 

Начальное заполнение данных по языковым таблицам

Для этого создаем процедуру наподобие указанной ниже с именем as_lang_{tableName}_createTexts.

Она создаст недостающие элементы для языка.  

ALTER PROCEDURE procedure [dbo].[as_lang_menu_createTexts]
 @lang nvarchar(16)
AS
BEGIN
    declare @langID int
    select @langID = id from as_langs where code = @lang

    insert into as_lang_menu (itemID, langID, name, title)
    select id, @langID, name, title
    from as_menu
    where id not in (select itemID from as_lang_menu where [langID] = @langID)

END

Передача параметра langID в хранимые процедуры.

В большинстве случаев langID вы можете взять из таблицы as_users по @username.

В некоторых случаях  параметр языка будет передаваться в хранимую процедуру напрямую как langID.

Управление локализацией для различных сущностей (товары, меню и др.)

Перевод сущностей делается через универсальную форму перевода отдельных полей под разные языки.

Есть некая сущность (entityCode), у которой есть поля (field).

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

<a href="#" class="as-form-modal btn btn-success" data-code="langField" data-itemid="page_1054_title"><i class="fa fa-language" aria-hidden="true"></i></a>

itemID - это {entityCode}_{entityID}_{fieldCode}

Для новой сущности необходимо реализовать доработки процедур (по примеру сущности page):  для таблицы fieldLangValues хранимые процедуры GetItems и UpdateField (прописать в них логику по сохранению полей для pages).

Таким образом для каждого поля, которое требуется перевести на языки добавляется подобная ссылка на модальную форму.

Как использовать локализацию на разных уровнях

Если вам необходимо использовать некую строковую константу, которая долждна быть локализована на другие языки, то используйте возможности, указанные ниже:

  • Если вы редактируете View, то используйте @Html.Lang(code, defValue, partCode)
  • Если вы редактируете в Controller, то используйте mng.Lang.GetText(code, defValue, partCode)
  • Если вы редактируете в SQL, то используйте функцию dbo.as_lang('code', 'defaultValue', 'partCode', @langID)
  • Если вы редактируете JS, то используйте as.lang(code, defaultValue)

Как использовать локализацию в хлебных крошках

В хранимой процедуре используем @langID, извлеченный из @urlParameters и функцию dbo.as_lang. См. пример:  

Как установить язык сразу при первом посещении

Для этого передавайте ссылку с кодом языка - параметр lang=en-us.

Например, https://falcon.web-automation.ru/?lang=en-us

Также вы можете установить принудительно язык в процедуре GetLayout параметр SELECT 1 - defaultLang и дополнительно в appsettings.json параметр defaultLang (дело в том, что  некоторые метки загружаются до получения данных GetLayout).

Как локализовать каталоги Lists

В процедуру search в параметре @filters передается спец параметр langID. 

В процедуру getItem можно передавать дополнительный необязательный параметр @parameters типа DictionaryParameter, в котором также передается langID. 

Примечания при внедрении локализации

Решение проблем при внедрении локализации: 

  1. Крупные текста с разметкой лучше писать в Notepad++ с подцветкой синтаксиса HTML и показом всех спец символов.
  2. Рекомендуется заменить пробел из текста (видимо из за вставки из Google Translate) на пробел вставленный с клавиатуры через Ctrl + H (иначе он в разметке обрабатывается как  )
  3. Крупные блоки верстки можно переводить через Google Translate (но при этом проверяйте, не сломались ли пути к картинкам, файлам). 
  4. Элементы управления локализацией сущностей обязательно делайте через Зеленые кнопки (модальная форма langField с вложенной таблицей fieldLangValues)
  5. Не подменяйте один язык на другой. Это может вызвать сбои в системных скриптах при переводе. Если по умолчанию нужен другой язык - подмените его в GetLayout.

Перевод строк в хранимых процедурах

Используйте процедуру as_lng для перевода отдельных строк (это позволит потом проще создавать переводные версии на другие языки, т.к. все эти метки будут храниться в таблице as_langTexts).

Пример использования: 

declare @s1 nvarchar(max)

exec dbo.as_lng @code = 'textCode', @text='Default value', @langID=1,  @part='part1', @res = @s1 output

Используя подобный подход вы автоматически сохраняете все значения в таблице для данного языка. Затем легко будет скопировать эти значения для другого языка и быстро перевести через таблицу langTexts. 

Код процедуры as_lng:

CREATE OR ALTER PROCEDURE [dbo].[as_lng]
@code nvarchar(128),
@text nvarchar(max),
@langID int = 0,
@part nvarchar(32) = '',
@res nvarchar(max) OUTPUT
AS
BEGIN

 if(@langID is null) begin
	return @text
 end

 select @res=[text] from as_langTexts where langID = @langID and code = @code and partCode = @part
 if(@res is null) begin
	insert into as_langTexts(langID, code, partCode, [text]) values(@langID, @code, @part, @text)
 	set @res = @text
 end

END

Платформа Falcon Space

Это снижение стоимости владения

за счет меньшего количества людей для поддержки

Это быстрое внесение изменений

по ходу эксплуатации программы

Это современный интерфейс

полная адаптация под мобильные устройства

Бесплатное обучение разработке на Falcon Space

Вы можете разрабатывать самостоятельно или сотрудничать с нами в плане веб-разработки на платформе Falcon Space.
Примечание