Смена языка интерфейса в программе "на лету"

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Смена языка интерфейса в программе "на лету"

Сообщение Ichthyander » 11.06.2015 00:31:49

Итак, чего я достиг и что сделал. Задача: сделать локализацию программы на английский язык. А еще вернее "родным" сделать для программы английский и добавить файл локализации my_program.ru.po
Что сделал?
1) Во-первых, включил в настройках проекта i18n, поставил чекбокс "обновлять файлы po автоматически при сохранении LFM". Указал папку languages, где будут лежать файлы локализации.
2) Добавил в общий модуль проекта в секции uses модуль DefaultTranslator
2) Во-вторых, вынес все строки, подлежащие переводу в отдельный модуль (это необязательно) в секцию resourcestrings. Теперь в файлах *.po будут автоматически добавляться строки из этой секции.
3) Сохранил все файлы LFM и тем самым самим IDE все тексты из компонентов форм, диалогов, фреймов и т.д. были вынесены также в эти файлы *.po.
4) Сделал соответствующие переводы на русский в файле my_program.ru.po.
Ну, вообщем все прекрасно работает, действительно удобно. В принципе любой пользователь программы может самостоятельно локализовать программу с помощью, к примеру, программы POEdit.
Но, как обычно появились ньюансы. Потребовалось сделать также ручное переключение языка. К примеру, русский пользователь в Германии запускает программу (а посколько немецкой локализации нет, да и удобнее все равно на русском), запускается английский интерфейс (так как он потому что по умолчанию, наверное). Конечно можно при загрузке принудительно загружать нужный язык, к примеру, вот так -lang ru. Но это неудобно пользователям. Поэтому написал такой код.
Код: Выделить всё
procedure TFrmMain.ActnLngEnExecute(Sender: TObject);
begin
  SetDefaultLang('en', LangDirectory);
end;

procedure TFrmMain.ActnLngRuExecute(Sender: TObject);
begin
  SetDefaultLang('ru', LangDirectory);
end;   

Код работает, но не до конца. Константы описанные в модулях *.pas переводятся. Никакие надписи из интерфейса программы не переводятся. И те и те строки присутствуют в файлах *.po. Что я мог упустить? Почему не переводится строки из LFM файлов?
Аватара пользователя
Ichthyander
постоялец
 
Сообщения: 267
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Смена языка интерфейса в программе "на лету"

Сообщение stanilar » 11.06.2015 08:16:25

Когда проектировал возможность перевода программы на другой язык, отказался от такого подхода. Дело в том, что логичный перевод всегда идет от контекста, это как перевод кнопки "Power", которая в русифицированной виндовс 10 переименовалась в "мощность".

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

Достигается это написанием собственных наследников для нужного набора контролов, в которых переводимое слово тянется из базы, а указание того, куда и как переводить тоже делается не сложно - в базу добавлена таблица "технический язык", в которой все названия лежат на языке разработчика + к ним дописываюся индекы записи в базе. Пользователь нажимает кнопку - ко все названиям приписываюся индексы, пользователь прямо из программы открывает диалог редактирования перевода, в котором указывает индекс и нужный перевод.

З.Ы. Если программа не сложна - неважно как ее переводить, но если функционал большой и сложный, то перевод должен быть выполнен переводчиком + специалистом + программистом, а это очень редкое сочетание качеств. Поэтому имеет смысл подумать о наиболее дружественном к пользователю функционале перевода. Причем, если Ваша программа - не результат работы коллектива разработчиков с тех.поддержкой, тестерами и самими программистами, очень советую обдумать именно вышеописанный подход.
stanilar
постоялец
 
Сообщения: 271
Зарегистрирован: 09.03.2010 19:09:02

Re: Смена языка интерфейса в программе "на лету"

Сообщение Лекс Айрин » 11.06.2015 09:32:24

А может, проще приготовить два меню и заменять одно другим при надобности?
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 4010
Зарегистрирован: 19.02.2013 16:54:51

Re: Смена языка интерфейса в программе "на лету"

Сообщение Ichthyander » 11.06.2015 09:48:14

stanilar писал(а):Когда проектировал возможность перевода программы на другой язык, отказался от такого подхода. Дело в том, что логичный перевод всегда идет от контекста, это как перевод кнопки "Power", которая в русифицированной виндовс 10 переименовалась в "мощность".

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

Достигается это написанием собственных наследников для нужного набора контролов, в которых переводимое слово тянется из базы, а указание того, куда и как переводить тоже делается не сложно - в базу добавлена таблица "технический язык", в которой все названия лежат на языке разработчика + к ним дописываюся индекы записи в базе. Пользователь нажимает кнопку - ко все названиям приписываюся индексы, пользователь прямо из программы открывает диалог редактирования перевода, в котором указывает индекс и нужный перевод.

О, как сложно. Только из-за того, что "контекст" может влиять на перевод. Но честно говоря у меня такой проблемы не возникло, да и если такое случится есть способы это решить. Я даже не замарачивался над этой "проблемой".

stanilar писал(а):З.Ы. Если программа не сложна - неважно как ее переводить, но если функционал большой и сложный, то перевод должен быть выполнен переводчиком + специалистом + программистом, а это очень редкое сочетание качеств. Поэтому имеет смысл подумать о наиболее дружественном к пользователю функционале перевода. Причем, если Ваша программа - не результат работы коллектива разработчиков с тех.поддержкой, тестерами и самими программистами, очень советую обдумать именно вышеописанный подход.

Я как раз выше и написал, что использование файлов *.po позволяет достаточно просто и удобно переводить эти файлы обычным пользователям с помощью специальных программ (есть как платные и бесплатные варианты), к примеру, я пользовался программой POEdit. Там кстати еще и подсказки по переводу в POEdit появляются, которые можно автоматом подставить. Нет, Вы зря отказываетесь от использование встроенных инструментов по локализации программ Lazarus.

Добавлено спустя 40 секунд:
Еще раз обращаюсь. Если кто-то использует механизмы локализации i18n в Lazarus и использовали переключение языков в программе "на лету" (использование процедуры SetDefaultLang (?)) - просьба помочь.

Добавлено спустя 3 минуты 51 секунду:
Лекс Айрин писал(а):А может, проще приготовить два меню и заменять одно другим при надобности?

А ведь дело не только не столько в пунктах меню: Caption всех визуальных компонентов в программе: TForm, TButtonTool, диалоги... И таких форм, диалогов, кнопок и прочего достаточно много. Да они и переведены... И нормально локализуются при запуске программе. Но вот на лету не получается. Хотя по идее должно. Может форму нужно как-то обновить, перерисовать, как при новом запуске форм?

Добавлено спустя 5 минут 48 секунд:
Кстати, что заметил Caption форм все-таки переводятся на лету. Но все остальное - нет
Аватара пользователя
Ichthyander
постоялец
 
Сообщения: 267
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Смена языка интерфейса в программе "на лету"

Сообщение Лекс Айрин » 11.06.2015 10:34:11

Ichthyander писал(а):Может форму нужно как-то обновить, перерисовать, как при новом запуске форм?


Как бы не помешало. Ведь форма то может не знать, что ее изменили. Надо будет попробовать.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 4010
Зарегистрирован: 19.02.2013 16:54:51

Re: Смена языка интерфейса в программе "на лету"

Сообщение McLion » 11.06.2015 11:36:34

В Lazarus есть пример для перевода, посмотри, может поможет! Ручное переключение языка там хорошо показано!
Код: Выделить всё
D:\lazarus\examples\translation
Аватара пользователя
McLion
постоялец
 
Сообщения: 302
Зарегистрирован: 06.02.2015 18:41:00

Re: Смена языка интерфейса в программе "на лету"

Сообщение Лекс Айрин » 11.06.2015 14:01:53

Меню спокойно заменяется динамически простым присваиванием

Код: Выделить всё
MainForm.Menu:=MainForm.MenuEng;

Причем, не надо даже ничего обновлять. Я не успел заметить момента смены языка. Сейчас буду пробовать динамически перевести другие компоненты.

Добавлено спустя 22 минуты 31 секунду:
Код: Выделить всё
MainForm.GroupBox1.Caption:='Font';

тоже не требует обновления...

Ichthyander, боюсь, что Вы делаете что-то не то... у меня получается. Caption и Hint легко меняются у любого компонента.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 4010
Зарегистрирован: 19.02.2013 16:54:51

Re: Смена языка интерфейса в программе "на лету"

Сообщение Ichthyander » 11.06.2015 15:34:04

McLion писал(а):В Lazarus есть пример для перевода, посмотри, может поможет! Ручное переключение языка там хорошо показано!
Код: Выделить всё
D:lazarusexamplestranslation

Спасибо, посмотрю как реализовано у них. Компиляция показало, что пеерключение языков происходит без проблем, даже направление письма меняется для семитский языков..

Добавлено спустя 6 минут 44 секунды:
Лекс Айрин писал(а):Меню спокойно заменяется динамически простым присваиванием

Код: Выделить всё
MainForm.Menu:=MainForm.MenuEng;

Причем, не надо даже ничего обновлять. Я не успел заметить момента смены языка. Сейчас буду пробовать динамически перевести другие компоненты.
На лету (динамически) не переводится не только меню, но и все другие контролы, за исключением Caption форм.

Лекс Айрин писал(а):
Код: Выделить всё
MainForm.GroupBox1.Caption:='Font';

тоже не требует обновления...
Я не понял Вас. Если я вручную в коде присвою новые локализованные строки текстовым свойства компонентам, то естественно, все поменяется.
Проблема в том, что процедура SetDefaultLang из модуля LCLTransaltor переводит не все, если это делает на лету (или динамически как Вы выражаетесь).
Лекс Айрин писал(а):Ichthyander, боюсь, что Вы делаете что-то не то... у меня получается. Caption и Hint легко меняются у любого компонента.

Я этого тоже боялся, поэтому и создал топик тут... Сейчас гляну как реализовано в /examples/translations/

Добавлено спустя 11 минут 49 секунд:
Судя по коду приложения translation_demo, мои подозрения подтверждаются. По сути SetDefaultLang [пока?] не переводит компоненты программы на лету. Вот оттуда кусочек кода:
Код: Выделить всё
{ This method is inherited from LocalizedForm and manually inserts translated
  strings in cases where DefaultTranslator cannot do this. }
procedure TMainForm.UpdateTranslation(ALang: String);
begin
  inherited;

  { The items of the radiogroup are not automatically handled by
    DefaultTranslator. Therefore, we have to assign the strings to the
    translated versions explicitly. }
  RgDrinks.Items[0] := rsBeer;
  RgDrinks.Items[1] := rsWine;
  RgDrinks.Items[2] := rsWater;

  { The label LblCurrentSelection is created by a Format statement. Since
    DefaultTranslator does not execute code we have to update the translation
    of the label here. It is sufficient to call RgDrinksClick here where the
    caption is re-composed by means of the Format statement. }
  RgDrinksClick(nil);
end;

Для того, чтобы в программе на лету переключался язык интерфейса они "целый лес городят": создают для всех форм общего потомка, в котором прописывают метод UpdateTranslation. В наследуемом методе они вручную(!) в коде обновляют текстовые надписи, которые SetDefaultLangне обновляет автоматически. Тот же самый метод SetDefaultLang, используемый в модуле DefaultTranslator в разделе initialization все прекрасно переводит, если он там вызывается с параметров ForceUpdate=False.
Вообщем, получается так: переключение на лету [пока] использовать не буду. Просто не хочу замарачиваться. Либо оставлю только автоматически перевод при запуске в разделе инициализации, либо с параметром командной строки -lang xx язык программы можно будет определить вручную.
Аватара пользователя
Ichthyander
постоялец
 
Сообщения: 267
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Смена языка интерфейса в программе "на лету"

Сообщение Лекс Айрин » 11.06.2015 15:55:12

Ichthyander писал(а):Проблема в том, что процедура SetDefaultLang из модуля LCLTransaltor переводит не все, если это делает на лету (или динамически как Вы выражаетесь).


А зачем мне SetDefaultLang? Я сейчас не спеша почти добавил смену языка на английский без всякого геморроя и дополнительных модулей. А до вечера успею еще и добавить обратную смену языка... Вам нужны шашечки или ехать?
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 4010
Зарегистрирован: 19.02.2013 16:54:51

Re: Смена языка интерфейса в программе "на лету"

Сообщение Alex2013 » 11.06.2015 16:39:30

Когда-то сделал специальную утилиту ConstantReMaker .
Занималась тем что просто заменяла любой текст в программе на обращение к двухмерному массиву, констант который сама же строила ..
Второй координатой был язык ...
Разумеется нужно чтобы весь текст хранился листинге но это не так уж сложно сделать
Просто заполнить все поля в при создании форм
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption:='Расчет градуировки объема бака";
Label1.Caption:=''Угол наклона:";
...
end;
Для современных условий лучше создать ини файл и заменять текст на функцию чтения из него
Последний раз редактировалось Alex2013 13.06.2015 21:13:28, всего редактировалось 2 раз(а).
Alex2013
энтузиаст
 
Сообщения: 687
Зарегистрирован: 03.04.2013 11:59:44

Re: Смена языка интерфейса в программе "на лету"

Сообщение alexs » 11.06.2015 16:41:43

И чего только люди не придумают - лишь бы штатными средствами не пользоваться...
Аватара пользователя
alexs
долгожитель
 
Сообщения: 3468
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Смена языка интерфейса в программе "на лету"

Сообщение Alex2013 » 11.06.2015 16:56:38

alexs писал(а):И чего только люди не придумают - лишь бы штатными средствами не пользоваться...

Все равно не весь текст в формах, а штатный способ если правильно понял работает исключительно с текстом в формах .
(Кроме того утиль писалась во времена "Чистого ДОСа")
Но способ хорош именно легкой реализаций переключения "на лету" и полуавтоматическим способом добавления МЯ-интерфейса в готовую программу . :idea:
Alex2013
энтузиаст
 
Сообщения: 687
Зарегистрирован: 03.04.2013 11:59:44

Re: Смена языка интерфейса в программе "на лету"

Сообщение Лекс Айрин » 11.06.2015 16:58:10

alexs и не говори.

Может, дело в том, что штатные средства не очевидны?
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 4010
Зарегистрирован: 19.02.2013 16:54:51

Re: Смена языка интерфейса в программе "на лету"

Сообщение alexs » 11.06.2015 16:58:46

Штатный прекрасно работает со ресурсными константами.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 3468
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Смена языка интерфейса в программе "на лету"

Сообщение Ichthyander » 11.06.2015 17:08:51

Люди! Я сделал локализацию в программе, просто вынеся все строковые функции в отдельный модуль и добавив модуль DefaultTranslator в секцию uses. И все прекрасно работает и переводится, причем используется популярные формат для файлов локализации po/mo. Зачем мне изобретать велосипед. Единственно, как оказаолось, для чего нужно писать код это для переключения "на лету" языка интерфейса. Зачем я буду писать свой транслейтор, если все уже есть в Lazarus.

Добавлено спустя 1 час 24 минуты 41 секунду:
Alex2013 писал(а):Все равно не весь текст в формах, а штатный способ если правильно понял работает исключительно с текстом в формах .

Неправильно поняли: я же писал выше, что локализацию можно делать на всех текстовых константах в программе, просто вынеся их в секцию resourcestrings в модуле. Текстовые свойства компонентов выносятся в файл *.po автоматом. Остается только сделать перевод *.po файлов. А для этого есть различные утилиты с визуальным интерфейсов, можно и просто текстовом редакторе.
Alex2013 писал(а):Но способ хорош именно легкой реализаций переключения "на лету"
Да нет, вот это как раз пока не очень удобно реализовано. По крайней мере, в пару кликов как и с остальными фишками в i18n справится не удается.
Аватара пользователя
Ichthyander
постоялец
 
Сообщения: 267
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot], Google Adsense [Bot], Yandex [Bot] и гости: 4

Рейтинг@Mail.ru