2016-05-25 9 views
1

мне нужно добавить Языки поддержки существующего классического сайт осиныКлассический ASP - Сайт локализация

«Лучшее» Решение, которое я нашел, чтобы инкапсулировать каждый текст функции, создать таблицу базы данных, где хранить, для каждого страницы, переводы и использовать объект словаря для получения правильного значения.

пример:

<div>Welcome to xy website</div> 
<button class="btn green">Login</button> 

становится

<div><%=TL("Welcome to xy website")%></div> 
<button class="btn" ><%=TL("Login")%></button> 

тогда функция TL должна быть, как это

Function TL(strInput) 
    Dim strTargetLanguage, strPageURL,objDict,strTmp1,strTmp2 
    if strInput<>"" then 
     ' First check if customer has set language.. else uses browser language 
     if request.cookies("culture")="" then 
      strTargetLanguage=lcase(left(request.servervariables("HTTP_ACCEPT_LANGUAGE"),2)) 
     else 
      strTargetLanguage=lcase(left(request.cookies("culture"),2)) 
     end if 
     ' if User's Language is not supported.... 
     if instr(strAcceptedLanguages,strTargetLanguage)= 0 then   
      strTargetlanguage="en" 
     end if 

     strPageURL=Request.ServerVariables("URL") 

     Set objDict=Server.CreateObject("Scripting.Dictionary") 
     objDict.Add "strPageUrl",strPageUrl 

     'Stored Procedure to load translation in the required language and for the target Page  
     cmd.CommandText="spDictionaryRead" 
     cmd.CommandType=4 
     cmd.Parameters("@LanguageID")=strTargetLanguage 
     cmd.Parameters("@PageUrl")=strPageURL 
     set rst=cmd.Execute() 

     if not rst.eof then 
      while not rst.eof 
       objDict.Add rst("txt"),rst(strTargetLanguage) 
       rst.movenext() 
      wend 
     end if 
     rst.close 

     if objDict.Exists(strInput)=true then 
      TL=objDict.Item(strInput)   
     else   
      ' Custom Function to translate using google 
      TL=Translate(strInput,"en",strTargetLanguage) 

      TL=Replace(TL,"'","''") 
      strInput=replace(strInput,"'","''") 
      'Add new Sentence to Dictionary 
      cmd.CommandText="spDictionaryWrite" 
      cmd.CommandType=4 
      cmd.Parameters("@PageUrl")=strPageURL 
      cmd.Parameters("@TXT")=strInput 
      cmd.Parameters("@TargetLanguage")= strTargetLanguage 
      cmd.Parameters("@TargetText")=TL 
      cmd.Execute() 

      set objDict=nothing 
     end if   
    else 
     TL="" 
    end if 
End Function 

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

Мне нужно «ТОЛЬКО», чтобы найти мудрый способ хранения словаря «где-то», чтобы избежать его перестройки.
Но что выбрать? Приложение, Сессия, objVariable в страницу, ???

прибегая к помощи немного я понимаю, что применение не является мудрым решением по многим причинам,

Session: Я стараюсь держать сессию очень тонкий: Я никогда бы не сохранить объект с 30-50-Кис, если я могу избежать .... если я не удалю его в конце самой страницы (если это стоит)?

Кто-то предлагает загрузить переводы в приложение как «простой массив», а затем построить словарь каждый раз, когда это требуется, но при загрузке предложений в словарь я могу проверить, является ли текущее предложение целевым предложением и извлекает перевод без использования словаря .. поэтому ни это не является мудрым решением

Я прочитал также о

Уточняющий компонент от Microsoft

, но не удалось найти какие-либо документы

Возможно, вы можете использовать некоторые компоненты .NET, такие как HashTable?

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

Может Pls предложить лучший подход или некоторые намеки?

+0

В прошлом я использовал аналогичный подход с одним отличием, функция удваивается как режим администратора, который позволяет функции удваивать в качестве интерфейса администратора, который принимает ввод из текстового поля. Этот подход позволяет обновлять базу данных, но вы также можете создать локальный файл кеша, я использовал файлы XML. Это очень гибко, потому что если вы не загружаете страницу в режиме администратора, функция просто извлекает данные из файлов кеша. – Lankymart

+1

Привет, Интересно, что решение TextBox: для этого сайта я использовал другой подход, поскольку частые пользователи: поскольку машинный перевод плох, я добавил модальный фрейм, где каждый пользователь, если не принимает автоматический перевод, может настраивать каждое предложение и иметь собственный словарь , Но как использовать XML-файл в качестве файла кеша? может дать мне пару советов? Спасибо! – Joe

+0

Если я получу время сегодня, я попытаюсь оставить более полный ответ, но подход действительно работает, и компании используют это в дикой природе уже более 15 лет. – Lankymart

ответ

1

Некоторое время назад я унаследовал проект от другого разработчика и на сегодняшний день в Classic ASP. Я не нашел более эффективного способа обработки локализации.

Основная предпосылка

  1. магазин пар ключ-значение в базе данных, структура мы использовали это keys таблицу, содержащих ключи и «раздел» (который обозначает конкретную группировку ключей). Затем у нас есть таблица values, которая содержит языковые локализации, связанные с ключом, с помощью отношения FK (1: M).

    ╔══════════════════════════════════════════════════════════════════╗ 
    ║  Keys Table             ║ 
    ╠══════════════╦══════════════╦═════════════════╦══════════════════╣ 
    ║ id (int, PK) ║ key (string) ║ section (string)║ editpanel (bit) ║ 
    ╚══════════════╩══════════════╩═════════════════╩══════════════════╝ 
    
    ╔═════════════════════════════════════════════════════════════════════╗ 
    ║  Values Table             ║ 
    ╠══════════════╦═════════════════╦═════════════════╦══════════════════╣ 
    ║ id (int, PK) ║ key_id (int, FK)║ lang (string) ║ value (string) ║ 
    ╚══════════════╩═════════════════╩═════════════════╩══════════════════╝ 
    
  2. Построить приложение ASP для создания XML из пар ключ-значение в базе данных. Применение в основном две страниц

    1. Перебирает поддерживаемые языки и разделы (определенно в таблице keys) в вложенном цикле, это то, как мы решим на логическом разделении файлов кэш. В рамках каждой итерации мы передаем работу на другую страницу через объект WinHttpRequest. Страница возвращает структуру XML, которая построена путем поиска в базе данных и вытаскивания всех пар ключ-значение, которые связаны с повторением итерации конкретного раздела.

    2. Как уже упоминалось, страница, специально построенная для вызова объектом WinHttpRequest, которая после запроса базы данных для пар секций «ключ-значение» конкретного раздела возвращает их в построенной на заказ структуре XML.

  3. магазин файловой структуры что-то вроде

    \packs\ ┐ 
         ├ \de\ 
         ├ \es\ 
         ├ \fr\ 
         ... etc 
    

    , который включает в себя подкаталог для каждого языка, поддерживаемого в базе данных.Каталоги должны быть доступны с помощью идентификатора веб-приложения (будь то IUSR или предварительно сконфигурированная учетная запись) с разрешением не менее Modify, позволяющим создавать и изменять файлы в кешированном формате XML.

    Сделанные на заказ файлов XML выглядеть примерно так

    <?xml version="1.0" encoding="utf-8" ?> 
    <language_pack> 
        <strings> 
        <string id="391" key="connect" editpanel="0" section="email"> 
         <![CDATA[Connect]]> 
        </string> 
        <string id="9" key="uploadimage" editpanel="0" section="common"> 
         <![CDATA[Upload Photo]]> 
        </string> 
        <string id="12" key="notes" editpanel="0" section="common"> 
         <![CDATA[Notes]]> 
        </string> 
        </strings> 
        <error_messages> 
        <error id="1" key="pleasebepatient"> 
         <![CDATA[\nThis action may take a little time!\nPlease be patient.\n]]> 
        </error> 
        </error_messages> 
        <info> 
        <langcode>gb</langcode> 
        <langname>English</langname> 
        <strings>194</strings> 
        <time>0</time> 
        </info> 
    </language_pack> 
    

    файла XML укороченным, чтобы держать вещи простыми, фактические файлы содержат гораздо больше значения

Основной локализацию затем приведенный в действие файлом #include, который добавляется на каждую страницу, которая должна поддерживать локализацию (она просто становится частью процесса сборки ess при работе в локализованных веб-приложениях).

#include мы вызываем locale.asp делает что-то похожее на то, что вы описываете в вопросе. Он состоит из различных функций, среди которых основные;

  • init_langpack(langcode, admin, section) - Ручки любой инициализации кэш-файла XML. langcode - это просто строковое представление языка, который вы хотите загрузить (сопоставляет имена каталогов, de, es и т. Д.). admin определяет, находимся ли мы в «режиме администратора» или нет, и ведем себя несколько иначе, если мы это делаем, задавая заголовки страниц и т. Д., А section - это XML-файл (который мы разделяем на разделы) мы хотим загрузить в объект XMLDOM. Он должен всегда вызываться перед попыткой доступа к ml_string() при загрузке XML.

  • ml_string(id, showcontrol) - Используются страницы ASP, где мы хотим вывести Локализация id является ключевой из XML/ключи таблицы (почему и ?, объяснят в бите), в то время как showcontrol Boolean используется для решить, когда страница отображается в «режиме администратора», чтобы мы могли показать локализацию в редактируемом поле или нет. Вы не всегда можете это сделать из-за того, как локализации размещены на странице (позволяя вам обрабатывать их по-разному, отображать панель внизу и т. Д.).

+0

Хммм .. Понимаю, с секцией вы не имеете в виду «страницу» справа? поэтому у вас может быть больше раздела на одной странице ... Но тогда, как понять, в каком разделе вы переводите? В любом случае XML может избежать использования Словаря со всеми его ограничениями: относительно БД Я использовал только 1 таблицу с полями, такими как key, page, en, de, fr, it ... В любом случае большое спасибо за воскресенье Время! – Joe

+0

Извините, @joe все еще размышляет над тем, чтобы добавить больше к этому ответу. В принципе процедура 'init_langpack()' должна вызываться всякий раз, когда вы хотите загрузить локализацию для определенного раздела * (это всего лишь логическая группировка локализаций) *. Таким образом, вы можете менять и изменять, как хотите, я обычно загружаю их на основе страницы, а затем имею «общий» раздел, который также загружается в каждый кеш-XML как часть поколения XML, что позволяет мне иметь конкретную локализации, используемые в приложении, которые загружаются с помощью любого раздела 'init_langpack()' call. – Lankymart

+0

Да, у меня есть «общий» раздел, на самом деле я выбираю с 'WHERE Page = 'xxx.asp' или 'common'' :-) , но все в порядке! Спасибо большое! – Joe

2

Я использую Application для кеширования некоторых объектов в классическом ASP, обычно в виде массива со значениями, полученными из базы данных, с помощью GetRows().

Session не подходит, поскольку это доступно только одному пользователю, но не всем пользователям нравится Application.

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

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

Например, чтобы создать файл кэша ...

<% 
datestamp = Year(Now()) & Month(Now()) & Day(Now()) & Hour(Now()) & Minute(Now()) & Second(Now()) 

set fs=Server.CreateObject("Scripting.FileSystemObject") 
set tfile=fs.CreateTextFile(Server.MapPath("\cache\language_" & datestamp)) 
tfile.WriteLine("<%") 
tfile.WriteLine("Set objDict=Server.CreateObject(""Scripting.Dictionary"")") 

'...your database code here.... 
     while not rst.eof 
      tfile.WriteLine("objDict.Add " & rst("txt") & ",rst(strTargetLanguage)") 
      rst.movenext() 
     wend 
'...etc etc... 

tfile.WriteLine("%>") 
tfile.close 
set tfile=nothing 
set fs=nothing 

Application("languagecache") = datestamp 
%> 

NB. Датестоп в имени файла существует, так что нет никакой проблемы при создании кеша.

Тогда в ваших ASP-страниц можно включить последнюю версию файла кэша с помощью Server.Execute ...

Server.Execute("\cache\language_" & Application("languagecache")) 

Это всего лишь пример. Вы также должны добавить код, чтобы обеспечить доступ к странице до того, как будет создан первый файл кэша, который будет получать контент из включенного файла, который всегда будет там. Вы также добавили бы в некоторый код, чтобы проверить, когда последний раз был создан файл кэша, и сгенерировали новый по истечении установленного времени. Возможно, это запланированная задача, так что некому бедовому пользователю не нужно ждать, пока файл кэша будет построен (или просто запустите его асинхронно).

+0

Привет, Джон, спасибо, что ответили. О приложении/сеансе, поскольку такое же предложение на английском языке может иметь различный перевод на другом языке в соответствии с контекстом, каждый раз, когда я загружаю только перевод для этой конкретной страницы. Если я сохраню приложение, наверняка избегаю читать из базы данных для большинства распространенных языков и страниц, но если мне повезет (т. Е. У меня много посещений из разных стран), так как у меня более 40 страниц, я мог бы найти на конец дня с некоторыми 200-400 массивами в приложении, каждый с 20-30 значениями: мне кажется, что много места используется. – Joe

+0

Если вы используете выделенный/VPS-сервер и имеете достаточную доступную память, это может быть неважно, если вы храните LOT в переменных приложения. Если вы находитесь на общем хостинге, это будет иметь значение. Вам нужно хранить ваши переводы в базе данных? Вы можете просто включить перевод файлов для каждого языка, который вы включаете динамически на основе пользовательского параметра (с помощью 'Server.Execute'). – johna

+0

имеют облачный VPS с 4 ГБ ОЗУ, но ОЗУ никогда не бывает достаточно ... Да, перевод должен быть в БД, потому что каждый (зарегистрированный) пользователь может его настроить, поэтому каждый раз, когда кто-то загружает страницу, нам нужно изменить относительную переменную приложения : target должен загружаться только один раз, а не для каждого предложения, которое нужно перевести. поэтому в этих условиях лучшим решением, вероятно, является сохранение его в массиве и передача его функции – Joe

Смежные вопросы