Как запихнуть строки в ресурсы или мультиязычный советник

 

Можно ли в MQL4/5 хранить наборы (массивы) строк в ресурсах? Делаю мультиязычный советник, который будет автоматом переключаться на локаль, в которой работает терминал.

Понимаю, что входные параметры extern, input останутся на английском, ибо переключить языки в комментариях там никак. Но все остальное можно интернационализировать (еле слово написал :)).
Самое простое завести 2-х мерный строковый массив, в котором будут хранится сообщения,  надписи на кнопках и т.д. 2-х мерный для русского и английского будет выглядеть так

#define LNG_COUNT 2  // кол-во языков
#define STR_COUNT 2  // кол-во фраз в языковом наборе 

string astr[LNG_COUNT][STR_COUNT] = {{"Привет", "Пока"}, {"Hello", "Bye"}};

 Конечно, этот массив/массивы можно вынести в отдельный включаемый файл, чтобы при работе глаза не мозолили. Но все же, можно ли запихнуть строки в ресурсы, как картинки или звуки?

 
Alexey Volchanskiy:

Можно ли в MQL4/5 хранить наборы (массивы) строк в ресурсах? Делаю мультиязычный советник, который будет автоматом переключаться на локаль, в которой работает терминал.

Понимаю, что входные параметры extern, input останутся на английском, ибо переключить языки в комментариях там никак. Но все остальное можно интернационализировать (еле слово написал :)).
Самое простое завести 2-х мерный строковый массив, в котором будут хранится сообщения,  надписи на кнопках и т.д. 2-х мерный для русского и английского будет выглядеть так

 Конечно, этот массив/массивы можно вынести в отдельный включаемый файл, чтобы при работе глаза не мозолили. Но все же, можно ли запихнуть строки в ресурсы, как картинки или звуки?

Я проще делаю. Функция, возвращающая один из двух вариантов текста. Просто вписываю вместо текста эту функцию с двумя строками на входе.
 
Artyom Trishkin:
Я проще делаю. Функция, возвращающая один из двух вариантов текста. Просто вписываю вместо текста эту функцию с двумя строками на входе.
А потом, если надо изменить текст, прыгаем по коду и ищем эти строки? Не, в маленькой программе такое годится, в большой хочется все держать централизованно. Тем более, языков может быть  >2
 
Alexey Volchanskiy:
А потом, если надо изменить текст, прыгаем по коду и ищем эти строки? Не, в маленькой программе такое годится, в большой хочется все держать централизованно. Тем более, языков может быть  >2
Если спецификация указателей С/С++ работает, то можно язык переключать смещение указателя многомерного массива и присвоение его одномерному массиву. И этот одномерный уже задействовать при текстовом выводе.
 
Alexey Volchanskiy:
А потом, если надо изменить текст, прыгаем по коду и ищем эти строки? Не, в маленькой программе такое годится, в большой хочется все держать централизованно. Тем более, языков может быть  >2
Та нее, просто частный пример.
 

Я делаю так:

string Mstr_eng[][3]=
  {
     {"      The class constructor CWin"},
     {"      Properties class object CWin:"},
     {"Window title","New window"},
     {"Header Type","CRowType1(0)"},
     {"X= offset from the vertical","50"},
     {"Y= offset from the horizontal","100"},
     {"B= window width","250"},
     {"Snap windows","left corner"},
     {"         The class constructor CRow"},
     {"Focus is on the line","0"},
     {"ADD","INSERT","DELETE"},
     {"         Properties class object CRow:"},
     {"Type line","CRowType1(0)"},
     {"Cell 1 (string)",""},
     {"Cell 2 (string)",""},
     {"Cell 3 (string)",""},
     {"Cell width 1 (int)",""},
     {"Cell width 2 (int)",""},
     {"Project","file name"},
     {"Code Generation","START"},
     {},
     {}
  };
string Mstr_rus[][3]=
  {
     {"      Конструктор класса CWin"},
     {"      Свойства объекта класса CWin:"},
     {"Заголовок окна","Новое окно"},
     {"Тип заголовка","CRowType1(0)"},
     {"X= отступ от вертикали","50"},
     {"Y= отступ от горизонтали","100"},
     {"B= ширина окна","250"},
     {"Привязка окна","левый угол"},
     {"         Конструктор класса CRow"},
     {"Фокус на строке","0"},
     {"ДОБАВИТЬ","ВСТАВИТЬ","УДАЛИТЬ"},
     {"         Свойства объекта класса CRow:"},
     {"Тип строки","CRowType1(0)"},
     {"Ячейка 1 (string)",""},
     {"Ячейка 2 (string)",""},
     {"Ячейка 3 (string)",""},
     {"Ширина ячейки 1 (int)",""},
     {"Ширина ячейки 2 (int)",""},
     {"Проект","имя файла"},
     {"Генерация кода","СТАРТ"},
     {},
     {}
  };
//--- перечисление именованных констант 
enum languages
  {
   English,
   Russian
  };
input languages      language;                // Languages
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- языковая поддержка
   if(language==English)
     {
      ArrayCopy(Mstr,Mstr_eng);
     }
   if(language==Russian)
     {
      ArrayCopy(Mstr,Mstr_rus);
     }
   return(0);
  }
 
Алексей, а условную компиляцию здесь нельзя применить? Не получится удобней?
Условная компиляция (#ifdef, #ifndef, #else, #endif) - Препроцессор - Основы языка - Справочник MQL4
Условная компиляция (#ifdef, #ifndef, #else, #endif) - Препроцессор - Основы языка - Справочник MQL4
  • docs.mql4.com
Условная компиляция (#ifdef, #ifndef, #else, #endif) - Препроцессор - Основы языка - Справочник MQL4
 

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

string initSpread,initProfitCurrencyPeriod,initProfitCurrency, ...;
bool Lang=false;

int OnInit()
 {
// Определение языка терминала
   Lang=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian");

// Перевод
  initSpread                 = Lang?"Спред":"Spread";
  initProfitCurrencyPeriod   = Lang?"Прибыль в валюте за выбранный период":"Profit in the currency for the selected period";
  ...
  initProfitCurrency         = Lang?"Прибыль в валюте":"Profit in the currency";
 }

 Вариант для трёх:

string initSpread;

int OnInit()
 {
// Определение языка терминала
   string Lang=(TerminalInfoString(TERMINAL_LANGUAGE));

// Перевод
   initSpread = (Lang=="Russian")?("Спред"):
                (Lang=="German") ?("Verbreitung"):
                                  ("Spread"); // по умолчанию английский
//-
  return(0);
 }

void OnTick() 
 {
  Comment(initSpread);
 }

Можно и так:

string initSpread[] = {"Spread", "Спред", "Verbreitung", "Propagation"};
string initProfit[] = {"Profit", "Прибыль", "Zunahme", "Bénéfice"};

int initLang;

int OnInit()
 {
//- Определение языка терминала
  string Lang=(TerminalInfoString(TERMINAL_LANGUAGE));
  initLang = (Lang=="Russian")?1:
             (Lang=="German") ?2:
             (Lang=="French") ?3:
                               0; // по умолчанию английский
//-
  return(0);
 }

void OnTick() 
 {
  Comment("Спред: ",initSpread[initLang],". Прибыль: ",initProfit[initLang]);
 }
 

по идее можно сделать csv файл с переводами и считывать его в OnInit

id ; English ; Russian

0 ; "spread" ; "Спрэд"

1 ; "profit" ; "Профит"

а файл уже запихнуть в ресурсы. Да и вообще такой файл можно сделать один на все проекты

 
Maxim Kuznetsov:

по идее можно сделать csv файл с переводами и считывать его в OnInit

id ; English ; Russian

0 ; "spread" ; "Спрэд"

1 ; "profit" ; "Профит"

а файл уже запихнуть в ресурсы. Да и вообще такой файл можно сделать один на все проекты

заодно можно реализовать то чего разработчики Mql никак не могут предоставить в библиотеках, а именно хотя-бы частично i18n :-)

string _(string orig) и string _(int idOrig) - трансляция строковых констант в текущий язык терминала.

и внешний тулз (программа-парсер) которая читает *.mq4 и *.mq5 и создаёт/обновляет этот самый CSV со строковыми константами.

тогда сценарий разработки/поддержки/перевода достаточно прост, как и в других системах:

  1. все "строки" которые увидит юзер  надо оформлять как _("строки")
  2. перед релизом прогоняем исходники через парсер, получаем *.csv содержащий все строковые константы
  3. отдаёт этот файл переводчику - он пишет грамотные переводы
  4. результат прикладываем как ресурс
 
Yuriy Asaulenko:
Если спецификация указателей С/С++ работает, то можно язык переключать смещение указателя многомерного массива и присвоение его одномерному массиву. И этот одномерный уже задействовать при текстовом выводе.
Вы хотели сказать - арифметика указателей? В MQL не работает, т.к. тутошние указатели не указывают на адреса памяти, это просто дескрипторы в виндовской интерпретации.