Русский язык + Lazarus + Linux

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

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

Русский язык + Lazarus + Linux

Сообщение oco » 12.02.2007 17:35:20

Как известно, в Линуксе у русскоязычного юзера может стоять несколько локалей: CP1251, KOI-8, UTF-8 и т.д.

Как можно написать программу, которая бы показывала нормальные русские буквы на любой локали? Для сишников такое решение есть - это gettext.

А для Лазаря или паскаля никто такого не встречал?
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение Sergei I. Gorelkin » 12.02.2007 19:05:23

Я бы назвал правильным решением скорее iconv, чем gettext. Все-таки gettext - это средство вытаскивания строк из .mo файлов, а в какой кодировке они там лежат - дело автора этих самых .mo.
Так вот, iconv встроен в rtl и преобразует все WideString<->AnsiString при условии подключения к программе модуля cwstring.
Функциональность gettext частично поддерживается модулем gettext.pp из состава fcl. Cуществует и более полная реализация: www.dybdahl.dk/dxgettext/
Наконец, сам Лазарь локализован с помощью того же механизма, только строки берутся прямо из .po файлов.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение oco » 13.02.2007 13:35:39

Sergei I. Gorelkin писал(а):Я бы назвал правильным решением скорее iconv, чем gettext. Все-таки gettext - это средство вытаскивания строк из .mo файлов, а в какой кодировке они там лежат - дело автора этих самых .mo.

Согласен
Sergei I. Gorelkin писал(а):Так вот, iconv встроен в rtl и преобразует все WideString<->AnsiString при условии подключения к программе модуля cwstring.

Смотрел исходники, но там при преобразовании WideString в AnsiString вся кириллица заменяется на знаки вопроса!
Sergei I. Gorelkin писал(а):Функциональность gettext частично поддерживается модулем gettext.pp из состава fcl. Cуществует и более полная реализация: www.dybdahl.dk/dxgettext/
Наконец, сам Лазарь локализован с помощью того же механизма, только строки берутся прямо из .po файлов.

Если можно, об этом поподробнее...
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение Sergei I. Gorelkin » 13.02.2007 16:01:58

oco писал(а):Смотрел исходники, но там при преобразовании WideString в AnsiString вся кириллица заменяется на знаки вопроса!

О каких исходниках речь? По умолчанию (в system.pp) да, заменяется вопросами, но при наличии в ОС функций преобразования они подключаются вместо того WideStringManager, который по умолчанию. В Windows используется WideCharToMultiByte, в Linux и прочих, где есть iconv, используется iconv. Фишка в том, что для этого нужно добавить в программу модуль cwstring, без него не работает.

oro писал(а):
Sergei I. Gorelkin писал(а):Функциональность gettext частично поддерживается модулем gettext.pp из состава fcl. Cуществует и более полная реализация: www.dybdahl.dk/dxgettext/
Наконец, сам Лазарь локализован с помощью того же механизма, только строки берутся прямо из .po файлов.

Если можно, об этом поподробнее...


Функциональность gettext.pp из fcl сводится, по сути, к одной ф-ции: TranslateResourceStrings, которая переводит все ресурсные строки модуля с помощью указанного .mo файла. Все локализуемые строки надо объявлять как resourcestring. Привычные _(), textdomain() и т.д. отсутствуют.
Зато они присутствуют в dxgettext. Он такой большой из-за того, что в состав входит (в Windows версии, по крайней мере) как целиком пакет gettext, так и несколько собственных утилит и подробная документация. В проект включается только модуль размером около 80кБайт в исходнике.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1395
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение oco » 13.02.2007 16:33:29

Sergei I. Gorelkin писал(а):при наличии в ОС функций преобразования они подключаются вместо того WideStringManager, который по умолчанию. В Windows используется WideCharToMultiByte, в Linux и прочих, где есть iconv, используется iconv. Фишка в том, что для этого нужно добавить в программу модуль cwstring, без него не работает.


Спасибо, буду пробовать.
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение oco » 14.02.2007 12:27:54

Ура, подключил модуль cwstring, и все заработало! :D
В общем, пишем все русские сообщения в Unicode в файл, а потом преобразовываем их в ANSI обычным присваиванием!

Надо будет еще попробовать локаль UTF-8
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение ab » 27.03.2007 01:08:09

Для сишников такое решение есть - это gettext.

Gettext используется для ПЕРЕВОДА, а что касается разных локалей, то здесь лучший вариант - iconv.

С
Код: Выделить всё
cwstring
у меня как-то не заладилось, меньше всего хочется писать все сообщения в файл, а потом присваивать, даже в gtk2 под koi8 столкнулся с проблемами с чтением-записью в файл.

Так что сделал свой юнит (на основе cwstring) который правильно перекодирует не только строки, но еще и формы - на лету.
То есть в IDE можно спокойно писать в своей локали по-русски: под другой локалью все будет ОК.

Для одной формы нужна ОДНА строчка кода :)
ab
незнакомец
 
Сообщения: 6
Зарегистрирован: 27.03.2007 00:50:05

Сообщение oco » 27.03.2007 12:16:33

ab писал(а):Gettext используется для ПЕРЕВОДА, а что касается разных локалей, то здесь лучший вариант - iconv


Ну да, файлы *.po с помощью iconv перекодируем в разные локали...

ab писал(а):Так что сделал свой юнит (на основе cwstring) который правильно перекодирует не только строки, но еще и формы - на лету.
То есть в IDE можно спокойно писать в своей локали по-русски: под другой локалью все будет ОК.

Для одной формы нужна ОДНА строчка кода :)


А можно взять у вас его, если не жалко?
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение ab » 02.04.2007 00:22:58

oco писал(а):А можно взять у вас его, если не жалко?

Запросто.
Хорошо работает с локалями UTF-8, KOI8-R - с другими не проверял.
Я пока не совсем разобрался насчет GTK2 под локалью не-UTF8:
имена файлов, StringList могут сохраняться в родной кодировке, а StringGrid, например, - в UTF8.
Но это решится - когда буду делать проект с GTK2.
Код: Выделить всё
(*
  A.Voitov zprokuror(cyka)narod.ru
  LAZARUS-FPC-LINUX codeset conversion routines
 
  The goal is easy-and-on-fly *.lrs conversion from codeset used by developer to
  user's system codeset without gettext, without separate message files etc.
 
  Now I only have to set my codeset below (by default it's mine - UTF-8) -
  DON'T FORGET ABOUT IT -
  and call LocalizeForm('TFormClassName') right after {$I TFormClassName.lrs} -
  see example below.
  This way form resource file will be converted to system codeset when form is
  creating.

  For gtk/gnome there's only one conversion routine
      function Localize(source:string):ansistring;
  For gtk2 resource MUST, I guess, be converted to UTF-8 anyway (if it's not yet),
  so I set current_codeset to UTF-8 with FORCE_UTF8 definition. Though if
  developer's codeset is UTF-8 then no form resource conversion needed.

  Localize is published function so it can be used again to convert string constants,
  resource strings in most cases with no care about user's and developer's codeset.
  But it's not enough sometime (file names, inifiles etc. can be wrong when gtk2
  works in koi8-r locale).
  That's why we've got some stuff th handle it without care.
  1. First one is TIconv object (I'm not sure it's best way to do maybe it would class?
     if so uncomment $DEFINE OBJ_IS_CLASS below)
  2. Second are uiconv_xxx functions
  They can be used to easy implement any valid conversions.

  EXAMPLES:
  1. Auto form conversion
     - set my codeset below: {$DEFINE DC_UTF8}
     - add LocalizeForm('TFormClassName') after {$I TFormClassName.lrs}
     <CODE>
       unit1;
       [...]
       initialization
         {$I unit1.lrs}
         LocalizeForm('TForm1');
       end.
     </CODE>
  2. TIconv object example:
     object is local variable here, but it can be global (create at startup,
     dead in the end) if it's always in-use.
     <CODE>
       function koi8r_to_utf8(S:string):string;
       var iConverter:pIconv;
       begin
         iConverter:=NewIconv('CP1251', 'UTF-8');
         Result:=iConverter.iconv(S);
         iConverter.Free;
       end;
     </CODE>
  3. uiconv_xxx example - obvious.
 
  APPENDIX
  i. KNOWN DEVELOPER'S CODESET DEFENITIONS:
   $DC_KOI8 (obvious)
   $DC_UTF8 (obvious) - default
   $DC_WIN  (CP1251)  - not tested yet
  ii. GTK2 NOTES
   As I found there's something wrong with some strings when gtk2 is used under
   koi8-r locale. OpenDialog.FileName is stored in my inifile as koi8-r string
   and then can't be loaded in MRU menu.
   So I've got a couple of functions here for that case: str2gtk and gtk2str.
   'str' means current codeset (locale)
  iii. This unit tested with dc_utf8 and user's locale koi8-r only
*)

unit iconv;
{* Developer's codeset. Must be set on design-time. Default is UTF8}
{.$DEFINE DC_KOI8}
{.$DEFINE DC_WIN}
{.$DEFINE DC_UTF8} //nothing defined so DC_UTF8 will be defined here
{$IFNDEF DC_UTF8}
    {$IFNDEF DC_KOI8}
        {$IFNDEF DC_WIN}
            {$DEFINE DC_UTF8}
        {$ENDIF DC_WIN}
    {$ENDIF DC_KOI8}
{$ENDIF DC_UTF8}

{* user acces to iconv functions}
{$DEFINE USER_ICONV}
{* TIconv object}
{$DEFINE USE_OBJECT}
{* Ticonv is class(TObject)}
{$DEFINE OBJ_IS_CLASS}

{* form-localization needed only with gtk1 or with gtk2 if developer's codeset
is not utf-8. First turn it of.}
{$UNDEF USE_LOCALIZE}
{* if widgetset is GTK2 ($IFDEF LCLGtk2) and developer's codeset is not DC_UTF8
   then we'd FORCE_UTF8 and turn on USE_LOCALIZE. And if widgetset is GTK1 then
   we USE_LOCALIZE too.}
{$IFDEF LCLGtk2}
    {$IFNDEF DC_UTF8}
         {$DEFINE USE_LOCALIZE}
         {$DEFINE FORCE_UTF8}
    {$ENDIF DC_UTF8}
{$ELSE LCLGtk2}
         {$DEFINE USE_LOCALIZE}
{$ENDIF LCLGtk2}

{$mode objfpc}
interface
uses
  {$IFDEF USE_LOCALIZE} LResources, Classes,{$ENDIF} initc, SysUtils;

  {* returns current codeset}
  function GetCodeset():ansistring;
  {$IFDEF USE_LOCALIZE}
  {* returns true if current codeset<>developer's codeset}
  function InvalidCodeset():boolean;
  {$ENDIF USE_LOCALIZE}
  {* basic string conversion - enough for localization.
     conversion from developer's codeset 2 user's codeset}
  function Localize(source:ansistring):ansistring;
  {with gtk2 converts utf8 to locale codeset and back}
  {$IFDEF LCLGtk2}
  function str2gtk(source:ansistring):ansistring;
  function gtk2str(source:ansistring):ansistring;
  {$ENDIF LCLGtk2}
  {* public access 2 iconv}
  {$IFDEF USER_ICONV}
  function uiconv(ic_usr:pointer; source:ansistring):ansistring ;
  function uiconv_open(ic_from, ic_to:ansistring):pointer ;
  procedure uiconv_close(ic_usr:pointer) ;
  {$ENDIF USER_ICONV}
  {* form conversion}
  procedure LocalizeForm(form_classname:ansistring);

{* iconv object/class}
{$IFDEF USE_OBJECT}
  type
    {$IFDEF OBJ_IS_CLASS}
    Ticonv=class(TObject)
    {$ELSE OBJ_IS_CLASS}
    pIconv=^Ticonv;
    Ticonv=object
    protected
    {$ENDIF OBJ_IS_CLASS}
      hIconv:pointer;
    public
      destructor Destroy;{$IFDEF OBJ_IS_CLASS}virtual;{$ENDIF OBJ_IS_CLASS}
    {$IFNDEF OBJ_IS_CLASS}
      procedure Free;
    {$ENDIF OBJ_IS_CLASS}
      constructor Create{$IFDEF OBJ_IS_CLASS}(cs_from, cs_to:ansistring){$ENDIF OBJ_IS_CLASS};
      function iconv(source:ansistring):ansistring;
    end;
    {$IFNDEF OBJ_IS_CLASS}
    function NewIconv(cs_from, cs_to:ansistring):TIconv ;
    {$ENDIF OBJ_IS_CLASS}
{$ENDIF USE_OBJECT}

implementation
uses dialogs;
{$linklib c}

const
  libiconvname='c';
  __LC_CTYPE = 0;
  _NL_CTYPE_CLASS = (__LC_CTYPE shl 16);
  _NL_CTYPE_CODESET_NAME = (_NL_CTYPE_CLASS)+14;
  CODESET = _NL_CTYPE_CODESET_NAME;
{developer's codeset names}
{$IFDEF DC_KOI8}
   DEV_CODESET='KOI8-R';
   DC_NAME='KOI';
   DC_NAME_EXT='R';
{$ENDIF DC_KOI8}
{$IFDEF DC_UTF8}
   DEV_CODESET='UTF-8';
   DC_NAME='UTF';
   DC_NAME_EXT='8';
{$ENDIF DC_UTF8}
{$IFDEF DC_WIN}
   DEV_CODESET='CP1251';
   DC_NAME='1251';
   DC_NAME_EXT='1251';
{$ENDIF DC_WIN}

type
  size_t   = cardinal;
  pSize    = ^size_t;
  psize_t  = pSize;
  cInt     = longint;
  piconv_t = ^iconv_t;
  iconv_t  = pointer;
  nl_item  = cint;
 
var //iconv pointers
  {$IFDEF LCLGtk2}
  ic_str2gtk, ic_gtk2str,
  {$ENDIF LCLGtk2}
  ic_localize  : iconv_t;

function nl_langinfo(__item:nl_item):pchar;cdecl;external libiconvname name 'nl_langinfo';
function iconv_open(__tocode:pchar; __fromcode:pchar):iconv_t;cdecl;external libiconvname name 'iconv_open';
function iconv(__cd:iconv_t; __inbuf:ppchar; __inbytesleft:psize_t; __outbuf:ppchar; __outbytesleft:psize_t):size_t;cdecl;external libiconvname name 'iconv';
function iconv_close(__cd:iconv_t):cint;cdecl;external libiconvname name 'iconv_close';

{* common procedures}
function GetCodeset():ansistring;
begin
Result:= ansistring(nl_langinfo(CODESET));
end;

function CodesetIs(CSNAME, CSEXT:ansistring):boolean ;
var CS:ansistring;
begin
  CS:=UpperCase(GetCodeSet);
  if ((pos(CSNAME,CS)<>0) and (pos(CSEXT,CS)<>0)) then Result:=true else Result:=false;
end;

{* main conversion procedure}
function _iconv(hiconv:iconv_t; source:ansistring):ansistring;
  const
    ESysEILSEQ      = 84;
    ESysE2BIG       = 7;
  var
    len:SizeInt;
    outlength,
    outoffset,
    outleft : size_t;
    srcpos,
    destpos: pchar;
    mynil : pchar;
    my0 : size_t;
begin
    mynil:=nil;
    my0:=0;
    // extra space
    len:=length(source);
    outlength:=len*3+1;    //setlength(result,outlength);
    Result:=StringOfChar(#0, outlength);
    //outlength:=len+1;
    srcpos:=pChar(source);
    destpos:=pchar(result);
    outleft:=outlength*2;
    while iconv(hiconv,@srcpos,@len,@destpos,@outleft)=size_t(-1) do
      begin
        case fpgetCerrno of
         ESysEILSEQ:
            begin
              { skip and set to '?' }
              inc(srcpos);
              pwidechar(destpos)^:='?';
              inc(destpos,2);
              dec(outleft,2);
              { reset }
              iconv(hiconv,@mynil,@my0,@mynil,@my0);
            end;
          ESysE2BIG:
            begin
              outoffset:=destpos-pchar(result);
              { extend }
              setlength(result,outlength+len);
              inc(outleft,len*2);
              inc(outlength,len);
              { string could have been moved }
              destpos:=pchar(result)+outoffset;
            end;
          else
            raise EConvertError.Create('iconv error '+IntToStr(fpgetCerrno));
        end;
      end;
    //setlength(result,length(result)-outleft div 2); // truncate string
    Result:=TrimRight(Result);// not shure it always works right
end;

{$IFDEF USE_OBJECT}
{* Ticonv *}
{$IFNDEF OBJ_IS_CLASS}
function _NewIconv(cs_from, cs_to:ansistring):pIconv ;
begin
  New( Result, Create);
  Result^.hIconv:=Pointer(iconv_open(pChar(cs_to),  pChar(cs_from)));
end;

function NewIconv(cs_from, cs_to:ansistring):TIconv ;
begin
  Result:=_NewIconv(cs_from, cs_to)^;
end;

procedure Ticonv.Free();
begin
  if @Self<>nil then Self.Destroy;
end;
{$ENDIF OBJ_IS_CLASS}

constructor Ticonv.Create{$IFDEF OBJ_IS_CLASS}(cs_from, cs_to:ansistring){$ENDIF OBJ_IS_CLASS};
begin {$IFDEF OBJ_IS_CLASS}
inherited Create;
hIconv:=Pointer(iconv_open(pChar(cs_to),  pChar(cs_from)));
{$ENDIF OBJ_IS_CLASS}
end;

destructor Ticonv.Destroy;
begin
   iconv_close(hIconv);
   Inherited;
end;

function Ticonv.iconv(source:ansistring):ansistring;
begin
   Result:=_iconv(hIconv, source);
end;
{$ENDIF USE_OBJECT}

{$IFDEF USER_ICONV}
function uiconv(ic_usr:pointer; source:ansistring):ansistring ;
begin
  Result:=_iconv(iconv_t(ic_usr), pchar(source));
end;

function uiconv_open(ic_from, ic_to:ansistring):pointer ;
begin
  Result:= iconv_open(pchar(ic_to), pchar(ic_from));
end;

procedure uiconv_close(ic_usr:pointer) ;
begin
  iconv_close(iconv_t(ic_usr));
end;
{$ENDIF USER_ICONV}

function Localize(source:ansistring):ansistring;
begin
  Result:=_iconv(ic_localize, source);
end;

{$IFDEF LCLGtk2}
function str2gtk(source:ansistring):ansistring;
begin
  Result:=_iconv(ic_str2gtk, source);
end;

function gtk2str(source:ansistring):ansistring;
begin
  Result:=_iconv(ic_gtk2str, source);
end;
{$ENDIF LCLGtk2}

{* form localization - only if use_localize}
{$IFDEF USE_LOCALIZE}
function InvalidCodeset():boolean;
begin
Result:=False;
{$IFNDEF FORCE_UTF8} Result:= not (CodesetIs(DC_NAME, DC_NAME_EXT));{$ENDIF FORCE_UTF8}
end;

{* converts form resource from developer's codeset to env codeset.
   it's empty procedure if widgetSet is gtk2 and dev's codeset is utf8.
   So USE_LOCCALIZE definition used }
procedure LocalizeForm(form_classname:ansistring);
    var res : TLResource;
        S : ansistring;
        RS, MS : TMemoryStream;
begin
    {$IFNDEF FORCE_UTF8} //always convert to utf8
    if not InvalidCodeset then  exit;
    {$ENDIF FORCE_UTF8}
    {find resource}
    res:=LazarusResources.Find(form_classname);
    RS:=TMemoryStream.create;
    MS:=TMemoryStream.create;
    {read form 2 RS}
    RS.Write(res.Value[1],length(res.Value));
    RS.Position:=0;
    {convert 2 text}
    LRSObjectBinaryToText( RS, MS);
    MS.Position:=0;
    {copy 2 string}
    SetLength(S, MS.Size);
    MS.Read(S[1], MS.Size);
    {convert 2 ccs or utf8 - under gtk2}
    S:=Localize(S);
    {copy back to ms}
    S:=Trim(S) + #0#0#0#0;  //doesn't work without it...
    MS.Position:=0;
    MS.Write(S[1],length(S));
    MS.Position:=0;
    RS.SetSize(0);
    {convert 2 binary RS}
    LRSObjectTextToBinary(MS, RS);
    RS.Position:=0;
    SetLength(S, RS.Size);
    {write 2 resource}
    RS.Read(S[1],RS.Size);
    res.Value:=S;
    MS.Free;  RS.Free;
end;
{$ELSE USE_LOCALIZE}
{* dummy proc for easy testing}
procedure LocalizeForm(form_classname:ansistring);begin {*} end;
{$ENDIF USE_LOCALIZE}

initialization
{$IFNDEF FORCE_UTF8}
  ic_localize := iconv_open(nl_langinfo(CODESET), DEV_CODESET); //main
{$ELSE FORCE_UTF8}
  ic_localize := iconv_open('UTF-8', DEV_CODESET);
{$ENDIF FORCE_UTF8}
{$IFDEF LCLGtk2}
  ic_str2gtk:= iconv_open('UTF-8', nl_langinfo(CODESET));
  ic_gtk2str:= iconv_open(nl_langinfo(CODESET), 'UTF-8');
{$ENDIF LCLGtk2}
finalization
  iconv_close(ic_localize);
{$IFDEF LCLGtk2}
  iconv_close(ic_str2gtk);
  iconv_close(ic_gtk2str);
{$ENDIF LCLGtk2}
end.

PS: не уверен насчет правильности коррекции размера выходной строки в основной функции и параметров iconv() при ошибках. Но, во всяком, случае, пока все работает для всех проверенных перекодировок.
Будут какие улучшения - обещайте поделиться.
ab
незнакомец
 
Сообщения: 6
Зарегистрирован: 27.03.2007 00:50:05

Сообщение oco » 02.04.2007 11:46:53

Спасибо!

Я так понял, форма в Лазарусе хранится в *.lrs файле?
Так значит этот юнит перекодирует всю форму (то есть и имена свойств, а не только значения этих свойств)?

А как насчет перевода - то есть перевода формы на разные языки?
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение ab » 03.04.2007 00:47:19

oco писал(а):Спасибо!
Я так понял, форма в Лазарусе хранится в *.lrs файле?
Так значит этот юнит перекодирует всю форму (то есть и имена свойств, а не только значения этих свойств)?

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

oco писал(а):А как насчет перевода - то есть перевода формы на разные языки?

Переводом я пока не озабачивался - делаю исключительно русскую программу.
ab
незнакомец
 
Сообщения: 6
Зарегистрирован: 27.03.2007 00:50:05

Сообщение Attid » 03.04.2007 12:36:57

ab
это токо переведет статичесике обьекты , так ?
тобишь если я потом в коде создаю листбокс и вручную заполняю его
то мне надо самому заботится о том что бы заполнять его в правельно кодировке ?

ЗЫ еще вопрос ко всем, как я могу определеть в какой локале запустили программу? тобишь получить значение переменной окружения LANG ??
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение oco » 04.04.2007 10:24:50

ДА


З.Ы.
Смотри в выложенном юните функцию
function GetCodeset():ansistring;

Или можно просто получить значение переменной окружения LANG :)
oco
незнакомец
 
Сообщения: 8
Зарегистрирован: 20.01.2007 15:05:56
Откуда: Хмельницкий

Сообщение ab » 10.04.2007 07:56:30

Значение LANG и некоторые другие функции для определения локали могут работать неправильно. У нас на реботе в какой-то mandrive koi8ru выдавался просто как RU.**. GetCodeset возвращает значение, которое заведомо подходит для использования в iconv.

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

Если берутся константы, resourcestrings, то обычно хватает:
Код: Выделить всё
listbox.add(Localize(russian_string_constant));

Если надо заполнять листбокс сразу кучей готовых значений, сабитых в код, удобнее использовать объект или пользовательские процедуры (см.ниже).

Если речь идет о данных, поставляемых с программой, принцип тот же. У себя в программе я ввел в заголовок архива бланков параметр codeset, который автоматически устанавливается в значение codeset системы, где архив создается. Потом, когда программа впервые запускается на другой системе, она просматривает доступные архивы бланков и перекодирует имена файлов, комментарий к архиву, примечания к бланкам с использованием
Код: Выделить всё
 
  function uiconv(ic_usr:pointer; source:ansistring):ansistring ;
  function uiconv_open(ic_from, ic_to:ansistring):pointer ;
  procedure uiconv_close(ic_usr:pointer) ;


С gtk2 немного сложнее - я пока не разбирался.

Вопрос: если кто пользовался юнитом, не возникало проблем с резервируемым размером выходной строки (это может выражаться в отсечении конца или добавлении мусора в конец)?
По замыслу
Код: Выделить всё
Result:=StringOfChar(#0, outlength);
и
Result:=TrimRight(Result);

должны это исключать, но х.з.?
ab
незнакомец
 
Сообщения: 6
Зарегистрирован: 27.03.2007 00:50:05

Сообщение Attid » 14.04.2007 11:42:58

ab
решил испробывать твое чудо техники

окружение у меня utf8
lazarus запускается скриптом с локалью 1251

ну значит первым делом
Код: Выделить всё
initialization
  {$I fdesk.lrs}
  LocalizeForm('TfmDesk');

компилирую , запускаю, ошибка
Код: Выделить всё
Invalid string constant on line 68

понимаю что не все так просто раскоментиваю
{$DEFINE DC_WIN}
компилирую , запускаю, запутилось (из под IDE)
запускаю отдельно от IDE таже ошибка.

где грабли ?

ЗЫ: очень много хинтов и варнингов, пока не смотрел но нельзя ли их как нибуть того ? хинты отключил директивой, а вот варнинги не знаю как.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2585
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

След.

Вернуться в Lazarus

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

Сейчас этот форум просматривают: Alex2013 и гости: 44

Рейтинг@Mail.ru