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

Вниз

Как перекодировать текст из Windows кодировки в Dos?   Найти похожие ветки 

 
Mishenka   (2004-02-19 14:41) [0]

Как перекодировать текст из Windows кодировки в Dos?
Делаю с помощью CharToOem, так он выдаёт ошибку EAccessViolation.
В чм может быть проблема?


 
Тимохов   (2004-02-19 14:43) [1]

код


 
zamkom   (2004-02-19 14:48) [2]

Вот тебе код как использовать CharToOem
CharToOem(@S[1], @S[1]);
где S : String;


 
Тимохов   (2004-02-19 14:51) [3]

@S[1] эквивалентно pchar(s)


 
zamkom   (2004-02-19 14:54) [4]

Тимохов © (19.02.04 14:51) [3]
Если заменить @S[1] на pchar(s) появляется ошибка.


 
Тимохов   (2004-02-19 14:59) [5]


> zamkom © (19.02.04 14:54) [4]

Т.е. вы оспариваете 3?


 
zamkom   (2004-02-19 15:02) [6]

Тимохов © (19.02.04 14:59) [5]
Я не оспариваю, я констатирую факт. :)


 
Mishenka   (2004-02-19 15:06) [7]

Вот код:


var F:TextFile;
P:PChar;

....

AssignFile(F,"Fi.dat");
Rewrite(F);
CharToOem(PChar("Оператор:"+Edit3.Text),P);
WriteLn(F,P);
CharToOem(PChar("Руководитель:"+Edit4.Text),P);
WriteLn(F,P);
CloseFile(F);


 
Тимохов   (2004-02-19 15:08) [8]

И что - он работает?
под p память выделяется?


 
Тимохов   (2004-02-19 15:09) [9]


> zamkom © (19.02.04 15:02) [6]

Интересно, правда есть ошибка.
Зато вот так все норамально

setlength(s1, length(s));
CharToOem(pchar(S), pchar(S1));

Интересно почему
CharToOem(pchar(S), pchar(S));
не работает?


 
Игорь Шевченко   (2004-02-19 15:11) [10]

function StrToOem(const AnsiStr: string): string;
begin
SetLength(Result, Length(AnsiStr));
if Length(Result) > 0 then
CharToOemBuff(PChar(AnsiStr), PChar(Result), Length(Result));
end;


 
MBo   (2004-02-19 15:15) [11]

>Тимохов
А если строка не константная? :)


 
Mishenka   (2004-02-19 15:18) [12]

В том-то и дело, что нихрена не работает. В чём трабл?


 
Тимохов   (2004-02-19 15:23) [13]


> В том-то и дело, что нихрена не работает. В чём трабл?

под p память наверное забыл выделить.


> MBo © (19.02.04 15:15) [11]


procecure p;
var
s: string;
begin
s := "дима";
chartooem(@s[1], @s[1]); // работает
chartooem(pchar(s), pchar(s)); // не работает
end;

интересно почему.

Примерно понятно, что здесь дело в константной строке. Только не очень понятно как именно это влияет.


 
Verg   (2004-02-19 15:33) [14]

Так , давай по пунктам
Строка - константа

> chartooem(@s[1], @s[1]); // работает

S[1] - заставляет компилер предварительно образовать отдельную копию (UniquString)


> chartooem(pchar(s), pchar(s)); // не работает


pchar(S)
Передает просто адрес строки символов без изменения.
Теперь задумайтес - где размещает компилер(а точнее линкер) Делфи константные строки?


 
Тимохов   (2004-02-19 15:37) [15]


> Verg © (19.02.04 15:33) [14]


> S[1] - заставляет компилер предварительно образовать отдельную
> копию (UniquString)

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


 
Игорь Шевченко   (2004-02-19 15:37) [16]


> где размещает компилер(а точнее линкер) Делфи константные
> строки


compiler.

Известно где - там, где их ближе всего с точки зрения процессора достать - в сегменте кода рядышком.


 
MBo   (2004-02-19 15:41) [17]

Трассировка показывает, что @s[1] приводит к вызову UniqueStringA, чего не делается при простом кастинге.
Для константной строки делается копия - в примере адрес меняется. А с кастингом к PChar он по-прежнему указывает на область памяти, предназначенную для констант.

procedure TForm1.Button2Click(Sender: TObject);
var s:string;
p:Pchar;
begin
s:="фффффффф";
//s:=StringOfChar("ф",8);
Memo1.Lines.Add(IntToHex(Integer(S),8));
p:=@s[1];
Memo1.Lines.Add(IntToHex(Integer(p),8));


 
Тимохов   (2004-02-19 15:42) [18]


> Игорь Шевченко © (19.02.04 15:37) [16]

О том где компилятор размещает константные строки думаю знает каждый школьник. Почему не работает исходный пример, также понятно.

Вопрос в другом, где описан этот

> S[1] - заставляет компилер предварительно образовать отдельную
> копию (UniquString)

факт?


 
Тимохов   (2004-02-19 15:43) [19]


> MBo © (19.02.04 15:41) [17]

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

Интересно документированная ли это особенность?


 
AKul   (2004-02-19 15:48) [20]


> Игорь Шевченко © (19.02.04 15:37) [16]

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

Процессору все-равно где они расположены. Ему одинаково их доставать из любого адреса. Организация памяти в Windows"е является FLAT-моделью. Да и нет такого понятия, как сегмент кода, есть страницы памяти с флагом ReadOnly. Вот как раз для секции кода PE-файла загрузчик и устанавливает такой атрибут.
А размещает он их там потому, что присваиваемая строка - это константа и меняться она не будет. Да и нересурсоемко размещать константные значения в памяти имеющей атрибуты как для чтения, так и для записи.


 
Verg   (2004-02-19 15:50) [21]


> [19] Тимохов © (19.02.04 15:43)


примерно тут:

When indexing is used to change the value of a single character in a string, a copy of the string is made if—but only if—its reference count is greater than one. This is called copy-on-write semantics.


 
Тимохов   (2004-02-19 15:56) [22]


> When indexing is used to change the value of a single character
> in a string, a

Это я знаю.
ИМХО отлюда обсуждаемый вопрос не следует.
ИМХО changin это когда s[1] := "aaa";
Здесь же не все так очевидно для компилятора.
Думаю, что если компилятор способен так умно разобрать, то что я хочу сделать, он просто достоин восхищения. :))))


 
Verg   (2004-02-19 15:57) [23]

Из того, что объяснения самых "страшных и невероятных" ошибок обычно находятся в конце глав хелпов, можно сделать выводы о том, КАК мы читаем эти хелпы. :)))


 
Игорь Шевченко   (2004-02-19 15:57) [24]

AKul © (19.02.04 15:48)

Процессору-таки не все равно, откуда их доставать. Почему рядышком - чтобы не было page faults лишних.


 
Amoeba   (2004-02-19 16:02) [25]

Это работающий код (из RxLib, модуль StrUtils.pas):

function StrToOem(const AnsiStr: string): string;
begin
SetLength(Result, Length(AnsiStr));
if Length(Result) > 0 then
CharToOemBuff(PChar(AnsiStr), PChar(Result), Length(Result));
end;


 
Тимохов   (2004-02-19 16:04) [26]


> Verg © (19.02.04 15:57) [23]

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

(Занесем на подкорку, как особенность дельфи в данном вопросе)


 
Verg   (2004-02-19 16:08) [27]


> Тимохов © (19.02.04 15:56)


Когда мы говорим @S[1] или передаем S[1] в качестве var в процедуру, то откуда компилеру знать, что это не есть тот самый случай "is used to change"?

Подумайте еще раз об этом и без горячки....

PS ИМХО Вы лезете "в бутылку"


 
Тимохов   (2004-02-19 16:10) [28]


> Verg © (19.02.04 16:08) [27]

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


 
AKul   (2004-02-19 16:14) [29]


> Игорь Шевченко © (19.02.04 15:57) [24]
> Процессору-таки не все равно, откуда их доставать. Почему
> рядышком - чтобы не было page faults лишних.


Вы чего??? :(
Процессору абсолютно все равно! А тем более расположены данные "рядышком" с кодом или нет (да и какой смысл у этой фразы???). "Данные" и "код" - это понятия для Вас, для меня; а для процессора: на какой адрес указывает CS:EIP - это и есть текущая инструкция (код), будь для Вас она хоть строкой.


 
Amoeba   (2004-02-19 16:19) [30]

Ну все, о вопросе забыли и началась "битва титанов"...


 
Игорь Шевченко   (2004-02-19 16:28) [31]

AKul © (19.02.04 16:14)

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


 
AKul   (2004-02-19 16:33) [32]


> Amoeba © (19.02.04 16:19) [30]

Вы правы...

> Mishenka (19.02.04 15:06) [7]
Как адрес строки-приемника Вы передаете неинициализированный указатель P

Исправте так:

var F:TextFile;
S:string
....

AssignFile(F,"Fi.dat");
Rewrite(F);
S:="Оператор:"+Edit3.Text;
CharToOem(pchar(S),pchar(S));
WriteLn(F,S);
S:="Руководитель:"+Edit4.Text;
CharToOem(PChar(S),PChar(S));
WriteLn(F,S);
CloseFile(F);

Sorry, если где-нибудь ошибся в синтаксисе, исправлял тут...


 
Андрей Сенченко   (2004-02-19 16:39) [33]

AKul © (19.02.04 16:33) [32]

Около месяца назад здесь было обсуждение по поводу того, что CharToOem(PChar(S),PChar(S));
Может приводить к ошибкам.

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


 
default   (2004-02-19 16:41) [34]

Игорь Шевченко © (19.02.04 16:28) [31]
" А компилятор все равно старается размещать константы ближе к тому месту, где они используются."
а у этой фразы какой смысл?


 
Игорь Шевченко   (2004-02-19 16:42) [35]

default © (19.02.04 16:41)

Быстрее доступ к данным.


 
AKul   (2004-02-19 16:44) [36]


> Игорь Шевченко © (19.02.04 16:28) [31]
> компилятор все равно старается размещать константы ближе
> к тому месту, где они используются.

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

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


 
AKul   (2004-02-19 16:48) [37]


> Андрей Сенченко © (19.02.04 16:39) [33]
>
> Около месяца назад здесь было обсуждение по поводу того,
> что CharToOem(PChar(S),PChar(S));
> Может приводить к ошибкам.
> Посмотрите - может еще не стерлось

Помню, я сам на него отвечал.
Но в приведеном мною коде в посте [32] не будет ошибки.
Хотите знать почему, - сами посморите на то, куда меня послали...


 
Игорь Шевченко   (2004-02-19 16:50) [38]


> большая вероятность того, что они могут быть скинут в swap-файл,
> чем если они будут находится в странице памяти выполняющегося
> в данный момент кода!


Вот тут мы об одном и том же.


> Потому что так ему проще!


Неа:) Проще ему, как раз, все данные собрать в одном месте. Как изменяемые, так и не изменяемые.


 
default   (2004-02-19 16:50) [39]

Игорь Шевченко © (19.02.04 16:42) [35]
имели ввиду swap-файл говоря о скорости?


 
zamkom   (2004-02-19 16:50) [40]

Андрей Сенченко © (19.02.04 16:39) [33]
Да примерно месяц назад было обсуждение по данному вопросу.
Автором был я. :-)
Поэтому и привел код
zamkom © (19.02.04 14:48) [2]


 
Игорь Шевченко   (2004-02-19 16:52) [41]

default © (19.02.04 16:50)

Имеется в виду время доступа к нужной странице. Данные сегмента кода в подавляющем большинстве случаев в swap-файл не попадают.


 
Verg   (2004-02-19 16:53) [42]


> [34] default © (19.02.04 16:41)


Константы компилер хочет размещать в таком месте, где бы их модернизация была невозможна. Его можно понять? :)
Единственным обладающим столь ценным атрибутом является сегмент кода (Read Only, ExecutAble).
помнишь как раньше было - ОЗУ, ПЗУ, RAM, ROM...

"А компилятор все равно старается размещать константы ближе к тому месту, где они используются." - это, ИМХО, просто метафора


 
AKul   (2004-02-19 17:05) [43]


> Игорь Шевченко © (19.02.04 16:50) [38]
Неа:) Проще ему, как раз, все данные собрать в одном месте. Как изменяемые, так и не изменяемые.


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


 
default   (2004-02-19 17:09) [44]

Verg © (19.02.04 16:53) [42]
"Константы компилер хочет размещать в таком месте, где бы их модернизация была невозможна. "
возможна
const
S = "72345";
...
begin
PChar(@S[1])^ := "1";
Caption := S // Caption = "12345"
...
разве только явно невозможна


 
Verg   (2004-02-19 17:17) [45]


> [44] default © (19.02.04 17:09)


О том что такое @S[1] было сказано достаточно выше.
Кроме того не надо относится к записям типа const A=B так буквально.
Это почти как директивы #define в С, т.е. почти как препроцессинг.

Немного не по теме, но все же ...
http://citforum.isurgut.ru/book/cook/selfmod.shtml


 
Игорь Шевченко   (2004-02-19 17:18) [46]

AKul © (19.02.04 17:05)


> это вопрос скорее к разработчикам компилятора - кто их знает,
> что они там наплодили...


Между прочим, наплодили очень много интересных решений для оптимизации по времени выполнения. В том числе и загрузку конвейеров процессора, и мимимизацию количества страничных отказов. Скажу даже больше - у Microsoft в ряде системных библиотек используется такое понятие, как OMAP (расшифровку, увы, не помню), но суть в том, что редкоиспользуемые части кода в процедурах разбросаны по разным страницам памяти, для того, чтобы освободить место для часто используемого кода. Получившийся результат выглядит как макаронный код. Но работает в итоге быстрее, чем если бы вся процедура была собрана в одном месте.

С уважением,


 
default   (2004-02-19 17:20) [47]

Verg © (19.02.04 17:17) [45]
есть статья эта, всю не читал ещё, но почему константы модифиц-ся и до этого знал(хоть могут и лежать в сегменте кода физически защищённым от записи...)


 
Verg   (2004-02-19 17:30) [48]


> [47] default © (19.02.04 17:20)


const S = "12345";

procedure TForm1.Button1Click(Sender: TObject);
begin
pchar(@S[1])^ := "1";
Caption := S;
end;

Может все же попробуешь исполнить этот код для ясности? :))


 
AKul   (2004-02-19 17:30) [49]


> Игорь Шевченко © (19.02.04 17:18) [46]
> Между прочим, наплодили очень много интересных решений для
> оптимизации по времени выполнения.

Здесь я полностью с Вами согласен!!!

С уважением, Андрей.


 
default   (2004-02-19 17:52) [50]

Verg © (19.02.04 17:30) [48]
var
Form1: TForm1;
X: Byte;

implementation

{$R *.dfm}

procedure Proc1;
begin
X := 5
end;

procedure TForm1.Button1Click(Sender: TObject);
begin

asm
MOV BYTE PTR [OFFSET Proc1 + 6], 7
end;
Proc1;
Caption := IntToStr(X)

end;

Кстати в той статье пишется "Замечание: среди начинающих программистов ходит совершенно
нелепая байка о том, что, дескать, если обратится к коду программы командой,
предваренной префиксом DS, Windows якобы беспрепятственно позволит его изменить.
На самом деле это ерунда; обратиться-то она позволит, а вот изменить – нет,
каким бы способом ни происходило обращение, т.к., защита работает на уровне физических страниц,
а не логических адресов."
ерунда не ерунда, а вышеприведённый код работает
Verg © (19.02.04 17:30) [48]
у меня этот код работает
если у тебя нет значит дело в ОС-ах


 
default   (2004-02-19 17:55) [51]

Verg © (19.02.04 17:30) [48]
бегло посмотрел, думал мой код скопировал...


 
Verg   (2004-02-19 18:05) [52]


> [50] default © (19.02.04 17:52)


Ну что ж, значит так тому и быть - у тебя своя правда, у меня - своя. :))

Видимо только мне мерещится устойчивый AV.... Write of address <такой-то>.

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


 
default   (2004-02-19 18:17) [53]

Verg © (19.02.04 18:05) [52]
а почему ошибка-то должна быть?
работаем как говорили с копией же
кстати значение константы дажt в отладчике не посмотреть...


 
Verg   (2004-02-19 18:32) [54]


> [53] default © (19.02.04 18:17)


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

const
S = "12345";

и
pchar(@S[1])^:=

это полная аналогия pchar(@"12345"[1])^ :=

Понимаешь? Ни S, ни "12345" не всопринимаются компилером как Huge String, да и с какой бы стати? Вот поэтому и не работаем с копией.

Пока это просто набор символов в сегменте кода.

Все, мне надоело....


 
default   (2004-02-19 18:57) [55]

Verg © (19.02.04 18:32) [54]
PChar(S)^ := "7";
по вашему такой код работает с "реальной" S и потому должен вызывать ошибку так как константы распол-ся и тд и тп
но в моей "плохой и бескультурной ОС" такое действие не приводит к ошибку кроме того данные не изменяются(константы) хотя мы по-вашему обращаемся через "реальный" адрес...
в CPU это всё выглядит весьма загадочно


 
Defunct   (2004-02-20 05:36) [56]

default © (19.02.04 18:57) [55]
Нельзя записать в страницу кода.
Убедитесь:

procedure TForm1.Button1Click(Sender: TObject);
begin
Asm
Call @@L2 // В стеке адрес возврата: L2
@@L2:
Pop EBx // В EBx адрес на команду Pop EBx
Mov EAx, 100h // Эта команда занимает 5 байт
Mov CS:[EBx], EAx // Пытаемся затереть команду Pop EBx
// Здесь Access Violation at CS:@@L2
End;
Caption := "Zzz";
end;


 
default   (2004-02-20 15:33) [57]

Defunct © (20.02.04 05:36) [56]
ёлки, я ж говорю об изменении кода через DS, ясно что через CS
ошибка будет
а так у вас работает?
здесь затирается RET, если б не затиралось ничего, то ошибки бы не было
вот только думаю что не каждая ОС такие вольности позволяет

procedure TForm1.Button1Click(Sender: TObject);
label
LabelForRET;
begin

asm
MOV BYTE PTR [OFFSET LabelForRET], 0
end;
Caption := "YO!";
LabelForRET:

end;


 
Игорь Шевченко   (2004-02-20 16:47) [58]

default © (20.02.04 15:33)

Запусти отладчик - оно рулез.
В окне CPU посмотри, чему равно значение CS и чему равно значение DS. Будешь удивлен.


 
Anatoly Podgoretsky   (2004-02-20 16:55) [59]

Игорь Шевченко © (20.02.04 16:47) [58]
Вообще то это мало о чем говорит, хто значения селектора, а на что оно указывает совсем другое дело. Специалисты сказали, что это для удобства сделали два разных селектора, в том числе и для защиты.


 
Amoeba   (2004-02-20 17:52) [60]

Модератор! Ау! Пора перебрасывать ветку в "Потрепаться".


 
default   (2004-02-20 18:33) [61]

Игорь Шевченко © (20.02.04 16:47) [58]
смотрел?и что?
вот ещё кусок статьи Касперски на эту тему
"Создание самомодифицирующегося кода требует знания некоторых тонкостей архитектуры Windows, не освещенных в документации, но одинаково реализованных на всех Windows-платформах, и активно используемых компилятором Visual C++ от Microsoft.
Для адресации 4 ГБ виртуальной памяти, выделенной в распоряжение процесса, Windows использует два селектора; один загружается в сегментный регистр CS, а другой – в регистры DS, ES и SS. Оба селектора ссылаются на один и тот же базовый адрес памяти (равный нулю), и имеют лимит в 4 ГБ. (Замечание: кроме перечисленных, Windows использует еще и регистр FS, в который загружает селектор сегмента, содержащего информационный блок потока).

Фактически существует всего один сегмент, вмещающий в себя и код, и данные, и стек процесса. Благодаря этому передача управления коду, расположенному в стеке, осуществляется близким (near) вызовом или переходом, и для доступа к содержимому стека использование префикса "SS" совершенно необязательно. Несмотря на то, что значение регистра CS не равно значению регистров DS, ES и SS, команды MOV dest,CS:[src]; MOV dest,DS:[src] и MOV dest,SS:[src] в действительности обращаются к одной и той же ячейке памяти.
Отличия между регионами кода, стека и данных заключаются в атрибутах принадлежащих им страниц: страницы кода допускают чтение и исполнение, страницы данных – чтение и запись, а стека – чтение, запись и исполнение одновременно.

Помимо этого, каждая страница имеет специальный флаг, определяющий уровень привилегий, необходимых для доступа к этой странице. Некоторые страницы – например, те, что принадлежат ОС, требуют наличия прав супервизора, которыми обладает только код нулевого кольца. Прикладные программы, исполняющиеся в кольце 3, таких прав не имеют, и при попытке обращения к защищенной странице вызывают исключение.
Манипулировать атрибутами страниц, равно как и ассоциировать страницы с линейными адресами, может только операционная система (или код, исполняющийся в нулевом кольце). Правда, в защите Win’95/98 есть дыры, позволяющие коду повысить свои привилегии до супервизора; но в Windows NT/2000 это уже не проходит."


 
Игорь Шевченко   (2004-02-20 18:36) [62]


> Отличия между регионами кода, стека и данных заключаются
> в атрибутах принадлежащих им страниц: страницы кода допускают
> чтение и исполнение, страницы данных – чтение и запись,
> а стека – чтение, запись и исполнение одновременно


Ну да, ну да...



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

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

Наверх





Память: 0.62 MB
Время: 0.008 c
8-6159
Please
2003-10-31 22:46
2004.03.03
Компонент Varian WorkShop


3-5944
Dummes
2004-02-05 14:53
2004.03.03
Что бы это значило?


1-6153
dr Tr0jan
2004-02-16 02:48
2004.03.03
TPageControl без закладок.


1-6047
jiurajhgjhgty
2004-02-18 21:32
2004.03.03
Создание Upgrade-ов к программам


7-6264
Suharew
2003-12-14 21:13
2004.03.03
Как программно узнать MAC адрес сетевухи





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский