Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.08.28;
Скачать: [xml.tar.bz2];

Вниз

Тип AniString   Найти похожие ветки 

 
Германн ©   (2011-05-13 02:30) [0]

Напомните мне пожалуйста какой смысл имеет (если имеет) для данного типа символ #0. Конкретно, функция Length его учитывает или нет?


 
MBo ©   (2011-05-13 05:25) [1]

>функция Length его учитывает или нет?
Нет


 
han_malign   (2011-05-13 08:54) [2]


> >функция Length его учитывает или нет?
> Нет

char(0) - является допустимым символом String в любом месте, при этом String неявно дополнено нулевым символом...

Length("123"#0"4") = 5
lstrlen(PChar("123"#0"4")) = 3
PChar("123"#0"4")[5] = #0 //без AV

Length( String( PChar("123"#0"4") ) ) = 3
SetString(s, PChar("123"#0"4"), 5); Length(s) = 5

З.Ы. фишечка синтаксиса - char(0)=#0=^@ (#13#10=#$D#$A=^M^J)


 
RWolf ©   (2011-05-13 09:27) [3]


> han_malign   (13.05.11 08:54) [2]

^символ — удобная вещь, спасибо.
//судя по тому, что она не подсвечивается редактором, о ней не знают даже сами разработчики Delphi.


 
Anatoly Podgoretsky ©   (2011-05-13 09:35) [4]

Ты противоречишь, то она не знает, то знает, факт успешной компиляции доказывает это. Может это ты не знаешь?


 
RWolf ©   (2011-05-13 09:41) [5]


> Anatoly Podgoretsky ©   (13.05.11 09:35) [4]

противоречие имело бы место, если бы над дельфи работал один программист.
а это, скорее, из разряда «левая рука не знает, что делает правая».


 
Anatoly Podgoretsky ©   (2011-05-13 09:45) [6]

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


 
Anatoly Podgoretsky ©   (2011-05-13 09:46) [7]


> Напомните мне пожалуйста какой смысл имеет (если имеет)
> для данного типа символ #0. Конкретно, функция Length его
> учитывает или нет?

Никакого. Length учитывает, доказали примерами.


 
han_malign   (2011-05-13 09:55) [8]

З.З.Ы. Главное не путать с ShortString(aka Pascal String):
var passtr: string[5];
...
passtr:= "123"#0"4";
PChar(passtr) = #5"123"{#0} // !!!


Если нужно привести ShortString к PChar, проще всего - PChar(String(passtr)), но нужно помнить, что создается временный экземпляр String, который уничтожается при выходе из области видимости.
то есть:
hf:= CreateFile(PChar(String(passtr)), ...);{выход из ОВ} - все путем
pch:= PChar(String(passtr));{выход из ОВ}
...
hf:= CreateFile(pch, ...);
- грабли, т.к. String(passtr) - уже отпущен...
Вылавливать такие грабли потом очень трудно, т.к. виртуальная память может все еще удерживаться менеджером памяти, а содержимое может все еще не быть испорченным другими операциями с памятью...
Ключевое слово здесь - может(как звезды расположатся)...


При этом:
var passtr5: string[5];...
passtr5:= "12345";
try
  passtr5[6] <> #0
except
on E: EAccessViolation do {а вы чего хотели?} ;
end;
passtr5:= "321";
passtr5[4] = "4"
passtr5[5] = "5"

- это на тот случай - если кто-то решит, что он самый умный(PChar(@passtr[1])), или действительно умный(passtr[ord(passtr[0])+1]:= #0), но забыл про вариант
sizeof(passtr[0])+(ord(passtr[0]))*sizeof(passtr[1]) = sizeof(passtr)...


 
MBo ©   (2011-05-13 10:07) [9]

Хмм... Я-то в [1] про финишный ноль подумал


 
Anatoly Podgoretsky ©   (2011-05-13 14:15) [10]

Это не #0 хоть и тоже значение, это завершающий ноль, для совместимости с PChar. Это не часть строки.


 
Германн ©   (2011-05-13 15:46) [11]

Да. Знать ничего не остается приемлемого, кроме PChar.


 
Anatoly Podgoretsky ©   (2011-05-13 16:28) [12]

> Германн  (13.05.2011 15:46:11)  [11]

В большинстве случаев это провал в производительности и неудобство.


 
MBo ©   (2011-05-13 16:31) [13]

>Знать ничего не остается приемлемого, кроме PChar.

Для какой такой особой цели???


 
Германн ©   (2011-05-13 16:46) [14]


> Для какой такой особой цели

Приемный накопительный буфер.


 
MBo ©   (2011-05-13 16:51) [15]

И чем AnsiString в данном случае не устраивает?


 
Anatoly Podgoretsky ©   (2011-05-13 17:03) [16]

> Германн  (13.05.2011 16:46:14)  [14]

string с предварительно установленой длиной, длину все равно надо
устанавливать, но для PChar еще и память запрашивать.


 
Германн ©   (2011-05-13 17:32) [17]


> И чем AnsiString в данном случае не устраивает?

Многочисленные SetLength.


 
sniknik ©   (2011-05-13 18:50) [18]

> Многочисленные SetLength.
ну так сделай одинарный, на максимум. чем не устраивает?


 
clickmaker ©   (2011-05-13 18:52) [19]

> Многочисленные SetLength

а какая разница? SetLength, Realloc...


 
Германн ©   (2011-05-13 19:06) [20]


> ну так сделай одинарный, на максимум. чем не устраивает?

Тем, что хотя это и буфер, но нужно работать с ним как со строкой.

> а какая разница? SetLength, Realloc

Не будет никаких Realloc. Будет array[0.1023] of char


 
Eraser ©   (2011-05-13 20:12) [21]

> [14] Германн ©   (13.05.11 16:46)

используйте TBytes.


 
Германн ©   (2011-05-13 20:19) [22]


> Eraser ©   (13.05.11 20:12) [21]
>
> > [14] Германн ©   (13.05.11 16:46)
>
> используйте TBytes.

Т.е. "тонкий" намек на то, чтобы я ушел с Д2007?
:)


 
sniknik ©   (2011-05-13 20:19) [23]

>  Тем, что хотя это и буфер, но нужно работать с ним как со строкой.
работай как с массивом, кто мешает? индексация только с 1, и вся разница.


 
Германн ©   (2011-05-13 20:35) [24]


> работай как с массивом, кто мешает? индексация только с
> 1, и вся разница.

У строк куча готовых функций типа Copy, Pos etc. Простое сложение двух строк опять же.


 
Ega23 ©   (2011-05-13 21:00) [25]


> Не будет никаких Realloc. Будет array[0.1023] of char

Тогда уж of AnsiChar. Подложи соломки заранее.


 
Германн ©   (2011-05-13 21:11) [26]


> Подложи соломки заранее.

Спасибо, подложу.


 
sniknik ©   (2011-05-13 21:59) [27]

> У строк куча готовых функций типа Copy, Pos etc. Простое сложение двух строк опять же.
и что? нет, не пойму, серьезно. понятно когда чего-то нет и поэтому использовать не удобно, но когда есть что-то дополнительное, пусть не нужное, при прочих равных, ну и что? не используй и все.

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

ты бы "на пальцах" как для идиотов пояснил бы.


 
Eraser ©   (2011-05-13 22:00) [28]

> [22] Германн ©   (13.05.11 20:19)

я всего лишь повторяю то, что рекомендует embarcadero http://edn.embarcadero.com/article/38703 . Практика это подтверждает, очень часто рассадник багов именно там, где используют строку, как буфер для любых данных. Особенно в крупных проектах, в которых несколько разработчиков.


 
Anatoly Podgoretsky ©   (2011-05-13 22:08) [29]

> Германн  (13.05.2011 17:32:17)  [17]

vs GetMem и плюс еще FreeMem


 
Anatoly Podgoretsky ©   (2011-05-13 22:13) [30]

> sniknik  (13.05.2011 20:19:23)  [23]

Так и массив можно объявить с 1
Кроме того и SetLength можно делать один раз и никакой разницы с
array[0.1023] of char
Кроме удобства


 
Anatoly Podgoretsky ©   (2011-05-13 22:17) [31]

> Eraser  (13.05.2011 22:00:28)  [28]

Они это утверждают в связи с Юникод, но кто же мешает вместо String написать
AnsiString


 
sniknik ©   (2011-05-13 22:26) [32]

> Кроме того и SetLength можно делать один раз и никакой разницы с
> array[0.1023] of char
> Кроме удобства
именно, все тоже, только удобнее, память не выделять, и есть дополнительные функции обработки.
единственное условие, не путать char и widechar, но как будто с массивом или pchar по другому, и решается все одним, правильным, объявлением типа, дальше оно тебе само врнинги и ошибки будет показывать...

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


 
sniknik ©   (2011-05-13 22:37) [33]

> Они это утверждают в связи с Юникод, но кто же мешает вместо String написать AnsiString
на самом деле, даже если написать WideString ничего не помешает использовать его как буфер под байты... единственное удобство потеряется, т.к. самому придется все высчитывать, а вот проблем от (цитата статьи) "или использует строку как буфер для данных" не вижу, и никогда не испытывал. в отличие от "в которых несколько разработчиков", тут постоянно, но только строки/буферы данных/и т.д. в этом не виноваты...


 
Eraser ©   (2011-05-13 22:40) [34]

> [31] Anatoly Podgoretsky ©   (13.05.11 22:17)

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


 
sniknik ©   (2011-05-13 23:07) [35]

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

хотя мой опыт подсказывает, чем меньше "закладок на будущее", усилий по "несуществующей еще совместимости", и больше внимание на текущее, тем без проблемней проект... а будущее, для какого то конкретного, может (и в 90% точно) и не наступит.
т.е. подавляющее большинство усилий на то "чтобы завтра было хорошо" тратится впустую. не тратить их вовсе, и когда понадобится просто переписать по новой/изменить было бы проще (но все одно тратят).


 
Anatoly Podgoretsky ©   (2011-05-13 23:48) [36]

> sniknik  (13.05.2011 22:37:33)  [33]

Да они просто нагнали страху, мол размер будет неправильный, ну и что?


 
Германн ©   (2011-05-14 02:28) [37]


> sniknik ©   (13.05.11 21:59) [27]
>
> > У строк куча готовых функций типа Copy, Pos etc. Простое
> сложение двух строк опять же.
> и что? нет, не пойму, серьезно. понятно когда чего-то нет
> и поэтому использовать не удобно, но когда есть что-то дополнительное,
>  пусть не нужное, при прочих равных, ну и что? не используй
> и все.
>
> вот когда говорят - у велосипеда нет колес, одна голая рама,
>  поэтому ездить на нем не могу. это понятно. а вот когда
> - у велосипеда куча запасных колес, плюс насосы, и т.д.
> всякие фенечки, гараж, и бесплатная обслуга, поэтому ездить
> на нем не могу.... ????? на тебя же это добро не навьючивают,
>  обслуживать тебя самого не заставляют, оно есть и есть,
>  чем нужно воспользуешься, что не нужно, пусть в гараже
> лежит. непонятно в общем.
>
> ты бы "на пальцах" как для идиотов пояснил бы.

Сегодня уже не в состоянии.


 
Германн ©   (2011-05-15 06:13) [38]


> Германн ©   (14.05.11 02:28) [37]

Значится так.
По протоколу TCP/IP посылаю сам себе и получаю от самого себя некие команды. Команды посылаются в текстовом виде типа "CCCxxx..x#13". Где CCC - трёхбуквенный идентификатор команды, xxx..x - параметры команды произвольной длины, #13 признак конца команды. (Да не убъёт меня АП за отсутствие #10).
Сейчас принял такое решение. Для  приемного накопительного буфера использую "настоящий" PAnsiChar. Zero-based array не прошёл по ряду причин. В обработчике события OnDataAvailable (библиотека ICS) ввёл локальную переменную типа AnsiString, в которую "копирую" содержимое данного буфера. Далее работаю в этом обработчике со строкой, применяя функциb Pos и Delete при разборке содержимого/принятого. По завершении обработки сохраняю остаток в буфере типа
MyStr:=PAnsiChar(St);
Превышения размера принятых данных более установленного при создании объекта вроде быть не должно, но это я частично учел. При приёме я проверяю размер уже существующих данных в буфере плюс принятых только что.


 
Anatoly Podgoretsky ©   (2011-05-15 07:32) [39]

> Германн  (15.05.2011 06:13:38)  [38]

Почему не убью, особенно для TCP/IP


 
DVM ©   (2011-05-15 23:14) [40]


> Германн ©   (13.05.11 16:46) [14]
>
> > Для какой такой особой цели
>
> Приемный накопительный буфер.

бери мой, может подойдет

unit uBuffer;

interface

const
 MinAllocation = 1024;

type

 TBuffer = class(TObject)
 private
   FStorage: PAnsiChar;                    
   FAllocation: integer;                  
   FHead: PAnsiChar;                      
   FTail: PAnsiChar;                      
   FSize: integer;                        
   function GetBytes(Index: Integer): PAnsiChar;
   procedure SetSize(ASize: integer);
 public
   constructor Create; overload;
   constructor Create(ASize: integer); overload;
   constructor Create(AStorage: PAnsiChar; ASize: integer); overload;
   constructor Create(ABuffer: TBuffer); overload;

   destructor Destroy; override;

   function Append(ABuffer: TBuffer): integer; overload;
   function Append(AStorage: PAnsiChar; ASize: integer): integer; overload;

   function Assign(AStorage: PAnsiChar; ASize: integer): integer; overload;
   function Assign(ABuffer: TBuffer): integer; overload;

   function Consume(ACount: integer): integer;
   procedure Empty;
   procedure Compact;
   function IsEmpty: boolean;
   function Expand(ACount: integer): integer;
   function Extract(ACount: integer): PAnsiChar;
   function Shrink(ACount: integer): integer;
   procedure Tidy;
   property Head: PAnsiChar read FHead;
   property Size: integer read FSize write SetSize;
   property Storage: PAnsiChar read FStorage;
   property Tail: PAnsiChar read FTail;
   property Allocation: integer read FAllocation;
   property Bytes[Index: Integer]: PAnsiChar read GetBytes;
 end;



 
DVM ©   (2011-05-15 23:15) [41]


implementation

//------------------------------------------------------------------------------

constructor TBuffer.Create;
begin
 Create(0);
end;

//------------------------------------------------------------------------------

constructor TBuffer.Create(ASize: integer);
begin
 if ASize > 0 then
   FAllocation := ASize
 else
   FAllocation := MinAllocation;
 FSize := 0;
 GetMem(FStorage, FAllocation);
 FHead := FStorage;
 FTail := FHead;
end;

//------------------------------------------------------------------------------

constructor TBuffer.Create(AStorage: PAnsiChar; ASize: integer);
begin
 if (ASize > 0) and Assigned(AStorage) then
   begin
    FAllocation := ASize;
    FSize := ASize;
    GetMem(FStorage, FAllocation);
    FHead := FStorage;
    Move(AStorage^, FStorage^, ASize);
    FTail := FHead + FSize;
   end
 else
   Create;
end;

//------------------------------------------------------------------------------

constructor TBuffer.Create(ABuffer: TBuffer);
begin
 if (Assigned(ABuffer)) and (ABuffer.Size > 0) then
   begin
     FAllocation := ABuffer.Size;
     FSize := ABuffer.Size;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     Move(ABuffer.Storage^, FStorage^, ABuffer.Size);
     FTail := FHead + FSize;
   end
 else
   Create;
end;

//------------------------------------------------------------------------------

procedure TBuffer.SetSize(ASize: integer);
begin
if FSize <> ASize then
   begin
     if FSize < ASize then
       Expand(ASize)
     else
       begin
         FSize := ASize;
         FTail := FHead + FSize;
       end;
   end;
end;

// Отсекает первые ACount символов ----------------------------------------------

function TBuffer.Consume(ACount: integer): integer;
begin
 if ACount > FSize then ACount := FSize;
 if ACount < 0 then ACount := 0;
 FHead := FHead + ACount;
 FSize := FSize - ACount;
 Result := ACount;
end;

// Отсекает последние ACount символов -------------------------------------------

function TBuffer.Shrink(ACount: integer): integer;
begin
 if ACount > FSize then ACount := FSize;
 if ACount < 0 then ACount := 0;
 FSize := FSize - ACount;
 if FTail > FHead + FSize then FTail := FHead + FSize;
 Result := ACount;
end;

// Расширение буфера -----------------------------------------------------------

function TBuffer.Expand(ACount: integer): integer;
var
 Spare, HeadSpace, TailSpace, Width, OldAllocation: integer;
 NewStorage: PAnsiChar;
begin
 result := FSize;
 if ACount <= 0 then exit;
 // Свободный (незанятый) объем буфера
 Spare := FAllocation - FSize;
 // Свободное место в начале буфера
 HeadSpace := FHead - FStorage;
 // Свободное место в конце буфера
 TailSpace := Spare - HeadSpace;
 // Размер (ширина) занятой части буфера
 Width := Tail - Head;
 // Если в буфере есть достаточно свободного места для добавления ACount байт
 if Spare >= ACount then
   begin
     // Если хвост меньше чем надо добавить
     if TailSpace < ACount then
       begin
         // Двигаем полезные данные в начало буфера
        Move(FHead^, FStorage^, FSize);
         // Начало данных совпадает с началом буфера
        FHead := FStorage;
         // Хвост данных на расстоянии width от головы
         FTail := FHead + Width;
       end;
   end
 else
   // Если в буфере недостаточно места для добавления count символов
   begin
     OldAllocation := FAllocation;
     // Общий объем буфера увеличиваем на count
     FAllocation := FAllocation + ACount;
     // Создаем временный буфер нужного размера
     GetMem(NewStorage, FAllocation);
     FillChar(NewStorage^, FAllocation, 0);
     if FStorage <> nil then
       begin
         // Копируем в него данные из старого буфера
         Move(FHead^, NewStorage^, FSize);
         // Старый буфер удаляем
         FreeMem(FStorage, OldAllocation);
       end;
     // Новый буфер заменяет старый
     FStorage := NewStorage;
     // Данные в начале буфера
     FHead := FStorage;
     // Хвоcт на расстоянии width от головы буфера
     FTail := FHead + Width;
   end;
 // Устанавливаем новый размер буфера
 FSize := FSize + ACount;
 // Возвращаем новый размер
 result := FSize;
end;

// Добавление данных в конец буфера --------------------------------------------

function TBuffer.Append(AStorage: PAnsiChar; ASize: integer): integer;
begin
 if Assigned(AStorage) and (ASize > 0) then
   begin
     Expand(ASize);
     Move(AStorage^, FTail^, ASize);
     FTail := FTail + ASize;
   end;
 result := FSize;
end;

// Добавление данных в конец буфера --------------------------------------------

function TBuffer.Append(ABuffer: TBuffer): integer;
begin
 result := Append(ABuffer.Storage, ABuffer.Size);
end;


 
DVM ©   (2011-05-15 23:15) [42]


// Извлечение первых ACount символов с их удалением из буфера ------------------

function TBuffer.Extract(ACount: integer): PAnsiChar;
var
 OldHead: PAnsiChar;
begin
 if ACount > FSize then ACount := FSize;
 if ACount < 0 then ACount := 0;
 OldHead := FHead;
 Inc(FHead, ACount);
 Dec(FSize, ACount);
 result := OldHead;
end;

//------------------------------------------------------------------------------

procedure TBuffer.Empty;
begin
 FSize := 0;
 FHead := FStorage;
 FTail := FHead;
end;

//------------------------------------------------------------------------------

function TBuffer.Assign(AStorage: PAnsiChar; ASize: integer): integer;
begin
 if Assigned(AStorage) and (ASize > 0) then
   begin
     FreeMem(FStorage, FAllocation);
     FSize := ASize;
     FAllocation := FSize;
     GetMem(FStorage, FAllocation);
     FHead := FStorage;
     Move(AStorage^, FStorage^, FSize);
     FTail := FHead + FSize;
   end;
 result := FSize;
end;

//------------------------------------------------------------------------------

function TBuffer.Assign(ABuffer: TBuffer): integer;
begin
 result := Assign(ABuffer.Storage, ABuffer.Size);
end;

//------------------------------------------------------------------------------

destructor TBuffer.Destroy;
begin
 FreeMem(FStorage, FAllocation);
 inherited Destroy;
end;

//------------------------------------------------------------------------------

function TBuffer.GetBytes(Index: Integer): PAnsiChar;
begin
 result := Head + Index;
end;

//------------------------------------------------------------------------------

procedure TBuffer.Tidy;
begin
 if FHead <> FStorage then
   begin
     if FSize = 0 then
       begin
         FHead := FStorage;
         FTail := FHead;
       end
     else
       begin
         Move(FHead^, FStorage, FSize);
         FHead := FStorage;
         FTail := FHead + FSize;
       end;
   end;
end;

//------------------------------------------------------------------------------

function TBuffer.IsEmpty: boolean;
begin
 result := FSize = 0;
end;

//------------------------------------------------------------------------------

procedure TBuffer.Compact;
var
 Temp: PAnsiChar;
begin
 if FSize > 0 then
   begin
     GetMem(Temp, FSize);
     Move(FHead^, Temp^, FSize);
     FreeMem(FStorage, FAllocation);
     FStorage := Temp;
     FAllocation := FSize;
   end
 else
   begin
     FreeMem(FStorage, FAllocation);
     FSize := 0;
     FAllocation := MinAllocation;
     GetMem(FStorage, FAllocation);
   end;
 FHead := FStorage;
 FTail := FHead + FSize;
 FAllocation := FSize;
end;

//------------------------------------------------------------------------------

end.


 
Германн ©   (2011-05-16 00:37) [43]


> DVM ©   (15.05.11 23:14) [40]
>
>
> > Германн ©   (13.05.11 16:46) [14]
> >
> > > Для какой такой особой цели
> >
> > Приемный накопительный буфер.
>
> бери мой, может подойдет
>

Спасибо, хорошая штука. Но в моем случае это из пушки по воробьям.


 
Германн ©   (2011-05-16 01:04) [44]


> Германн ©   (16.05.11 00:37) [43]
>
>
> > DVM ©   (15.05.11 23:14) [40]

Хотя. На всякий случай код сохранил. Если задача усложнится, то он может пригодиться.


 
Германн ©   (2011-05-16 03:26) [45]


> бери мой, может подойдет

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


 
Германн ©   (2011-05-16 03:31) [46]


> Anatoly Podgoretsky ©   (15.05.11 07:32) [39]
>
> > Германн  (15.05.2011 06:13:38)  [38]
>
> Почему не убью, особенно для TCP/IP
>

Потому что лень будет разбираться с кодом. :)
Ведь вывод в визуальный контрол у меня не планируется даже. :)



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2011.08.28;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.61 MB
Время: 0.005 c
1-1265138738
Vincent
2010-02-02 22:25
2011.08.28
Как прочитать память у DLL (ReadProcessMemory):DllName.dll+offset


8-1215338411
NIK
2008-07-06 14:00
2011.08.28
basswma


15-1304672702
OW
2011-05-06 13:05
2011.08.28
С наступающим днем связи!


15-1304713794
Юрий
2011-05-07 00:29
2011.08.28
С днем рождения ! 7 мая 2011 суббота


15-1304785332
TUser
2011-05-07 20:22
2011.08.28
delphi for html/javascript ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский