Локализация программ

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Локализация программ

Сообщение Sanya Z » 06.08.2004 (Пт) 2:00

Опять вот вопрос про перевод на другие языки интерфейса...
Перевод разумеется легче делать через ИНИ-файлы. Прочитал в одной книге такой совет...
Цитата: "Подписи к элементам управления, находящимся на этой форме, соответствует ключ, который называется так же, как и элемент управления. В результате при открытии формы запускается цикл, в котором ОПРАШИВАЮТСЯ все элементы управления расположенные на форме, и соответствующие им текстовые строки считываются из языкового файла".

Пример ИНИ-файла был таков:
[Form1]
btnOk.Caption=OK
btnCancel.Caption=Отмена
lblmain.Caprtion=Главная тема
....ну и в таком духе.

Я вот не понял как нужно в цикле все это опрашивать :?: Я всегда считывал каждый параметр, а вот до цикла не догоняю :oops: :arrow:
И пусть в моих поступках не было логики...

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 06.08.2004 (Пт) 8:40

Код: Выделить всё
Dim c As Control
For Each c In Form1
    c.Caption = "Hello!"
Next

это?

soljen
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 69
Зарегистрирован: 06.05.2004 (Чт) 15:47
Откуда: Из темноты...

Сообщение soljen » 06.08.2004 (Пт) 10:06

Доброго времени суток!

А если использовать файл ресурсов!
И оттудава считывать все подписи, да и вообще все всевозможные сообщения...
Но нужно это всё закрутить.... чтоб не путалось в дальнейшем!
Тиха украинская ночь, но сало надо перепрятать...
(R)Jeka

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 06.08.2004 (Пт) 10:07

Я бы написал так:
...
for each c in me.controls
...

Sebas
Неуловимый Джо
Неуловимый Джо
Аватара пользователя
 
Сообщения: 3626
Зарегистрирован: 12.02.2002 (Вт) 17:25
Откуда: столько наглости такие вопросы задавать

Сообщение Sebas » 06.08.2004 (Пт) 11:04

В VB6 это неудобно.
В VB.NET есть специальный SDK. ДА и то, проще сначала создать проект, а потом написать аддин который выдирает текст в нужное место
- Я никогда не понимал, почему они приходят ко мне чтобы умирать?

sebas<-@->mail.ru

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 06.08.2004 (Пт) 11:20

Ennor писал(а):Я бы написал так:
...
for each c in me.controls
...

А какая разница?
(это вопрос, а не утверждение)

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 06.08.2004 (Пт) 15:20

btnOk.Caption=OK


Лучше просто:

btnOk="OK"

И при переборе контролов присваивать в зависимости от типа контрола. То есть для каких-то контролов надо присвоить только Caption? Каких-то нужно присвоить ToolTipText, для Grid-a колонки.
И не надо забывать что локализировать придется и просто строки для того-же MsgBox-a к примеру...

Вот примерчик функции локализации (выдрано из одной программ):

Код: Выделить всё
'*************************************************************
' Процедура локализации объектов программы
'*************************************************************
Public Sub SetLang(sName As String, ColControls As Object, cf As FormLanguage)
    Dim c As Control, i As Integer, j As Integer, s As String, iCharSet As Byte
    cf.LoadFormLanguage sName
    iCharSet = g_ca.GetCurrentCharSet
    For Each c In ColControls
        Select Case TypeName(c)
            Case "Label", "CheckBox", "CommandButton", "OptionButton"
                If 0 = InStr(c.Tag, "-") Then
                    c.Caption = cf.ControlLang(c, "")
                    c.Font.Charset = iCharSet
                End If
                If 0 < InStr(c.Tag, "+") Then c.ToolTipText = cf.ControlLang(c, "T")
            Case "Frame"
                If 0 = InStr(c.Tag, "-") Then
                    c.Caption = " " & cf.ControlLang(c, "") & " "
                End If
            Case "CalPopUp"
                c.TodayText = g_cl(g_ExControls & "CalendarTodayText")
            Case "ButtonBar"
                c.Font.Charset = iCharSet: c.GroupsFont.Charset = iCharSet
                With c.ButtonGroups
                    For i = 1 To .Count
                        With .Item(i)
                            If 0 = InStr(.Tag, "-") Then .Caption = cf.ControlLang(c, .Key)
                            If 0 < InStr(.Tag, "+") Then .ToolTipText = cf.ControlLang(c, "T-" & .Key)
                            For j = 1 To .GroupItems.Count
                                With .GroupItems(j)
                                    If 0 = InStr(.Tag, "-") Then .Caption = cf.ControlLang(c, .Key)
                                    If 0 < InStr(.Tag, "+") Then .ToolTipText = cf.ControlLang(c, "T-" & .Key)
                                End With
                            Next j
                        End With
                    Next i
                End With
            Case "GridEX"
                If 0 = InStr(c.Tag, "-") Then SetGridLang c, cf, True
            Case "TabStrip"
                If 0 = InStr(c.Tag, "-") Then
                    With c.Tabs
                        For i = 1 To .Count
                            With c.Tabs(i)
                                If 0 = InStr(.Tag, "-") Then .Caption = cf.ControlLang(c, .Key)
                                If 0 < InStr(.Tag, "+") Then .ToolTipText = cf.ControlLang(c, "T-" & .Key)
                            End With
                        Next i
                    End With
                End If
            Case "Toolbar"
                With c.Buttons
                    For i = 1 To .Count
                        With .Item(i)
                            Select Case .Style
                                Case tbrDefault, tbrCheck
                                    s = .Tag
                                    If 0 = InStr(s, "-") Then .Caption = cf.ControlLang(c, .Key)
                                    If 0 < InStr(s, "+") Then .ToolTipText = cf.ControlLang(c, "T-" & .Key)
                            End Select
                        End With
                    Next i
                End With
            Case "SSTab"
                If 0 = InStr(c.Tag, "-") Then
                    j = c.Tab
                    For i = 0 To c.Tabs - 1
                        If c.TabVisible(i) Then
                            c.Tab = i
                            c.TabCaption(i) = cf.ControlLang(c, "C-" & i)
                        End If
                    Next i
                    c.Tab = j
                End If
        End Select
    Next c
End Sub


А если использовать файл ресурсов!
И оттудава считывать все подписи, да и вообще все всевозможные сообщения...


Можно и так.
Только INI-шку юзера сами могут поправить/дополнить...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Ennor
Конструктивный критик
Конструктивный критик
 
Сообщения: 2504
Зарегистрирован: 18.12.2001 (Вт) 3:58
Откуда: Калуга -> Москва

Сообщение Ennor » 06.08.2004 (Пт) 18:36

tyomitch писал(а):
Ennor писал(а):Я бы написал так:
...
for each c in me.controls
...

А какая разница?
(это вопрос, а не утверждение)

Не люблю использовать дефолты. Ненадежно...

EvilCoder
Посланец джихада
Посланец джихада
Аватара пользователя
 
Сообщения: 706
Зарегистрирован: 25.01.2004 (Вс) 15:08

Сообщение EvilCoder » 06.08.2004 (Пт) 20:59

:arrow: <DELETE> :arrow: 8)
Последний раз редактировалось EvilCoder 12.05.2007 (Сб) 16:49, всего редактировалось 1 раз.
<<------- EvilCoder ------->>

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 07.08.2004 (Сб) 1:09

Andrey Fedorov писал(а):Можно и так.
Только INI-шку юзера сами могут поправить/дополнить...


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

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 07.08.2004 (Сб) 1:22

EvilCoder писал(а):Есть прекрассная Книжка от Microsoft Press :)
"Microsoft Visual Basic 6.0 Programmer`s Guide" - Переведенная на Русский... Советую преобрести :D

Я к чему, Так вот там есть Глава "Локализация приложений" - там написано что строки надо хранить в Ресурсах :!: :roll: Потому ... что легче писать обращение к строкам... и изменять ресурсы в готовом ЕХЕшнике. И нет Лишних Файлов!


Заинтересовался...вот поискал в поисковике, есть в магазине библио-глобус, стоит 319 руб...
В НЕЙ ЧТО ПРАВДА 959 страниц???
И пусть в моих поступках не было логики...

EvilCoder
Посланец джихада
Посланец джихада
Аватара пользователя
 
Сообщения: 706
Зарегистрирован: 25.01.2004 (Вс) 15:08

Сообщение EvilCoder » 07.08.2004 (Сб) 12:09

:arrow: <DELETE> :arrow: 8)
Последний раз редактировалось EvilCoder 12.05.2007 (Сб) 16:52, всего редактировалось 1 раз.
<<------- EvilCoder ------->>

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 09.08.2004 (Пн) 2:22

У меня тут ещё один вопрос появился...
При считывании несуществующего ключа из ИНИ-файла функция возвращает какое-то слово, например, NoKey. И получается, что если какую-то строку(-и) из ИНИ удалили, то при замене Caption'ов на национальные, кнопки и названия меню будут иметь Caption = "NoKey"

Вот соответственно вопрос: а как этого не допустить? Ведь в каждой строке переименования не поставишь If str<>"nokey" then... И т.д. Т.е. надо если ключа нет, то кэпшн оставлять в неизменном состоянии.
И пусть в моих поступках не было логики...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 09.08.2004 (Пн) 7:10

Только INI-шку юзера сами могут поправить/дополнить...

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


Я не говорил что это недостаток - наоборот, это как раз преимущество...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 09.08.2004 (Пн) 7:17

Вот соответственно вопрос: а как этого не допустить? Ведь в каждой строке переименования не поставишь If str<>"nokey" then... И т.д. Т.е. надо если ключа нет, то кэпшн оставлять в неизменном состоянии.


А почему, собственно нет - что мешает-то?

Нормальный принцип - если нет строчки локализации на русском (к примеру) то вместо нее подставляется строка на английском. В результате то-же слово OK достаточно на русском просто не нужно описывать.
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

soljen
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 69
Зарегистрирован: 06.05.2004 (Чт) 15:47
Откуда: Из темноты...

Сообщение soljen » 09.08.2004 (Пн) 9:58

Доброго времени суток!

И ещё раз хочу обратить ваше внимание на то, что использование файла ресурсов совершенно исключает редактирование строк пользователем! А так как обычных юзеров предостаточно, то это может послужить и кое-какой защитой программы.
Но моё дело предложить!
Тиха украинская ночь, но сало надо перепрятать...
(R)Jeka

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 09.08.2004 (Пн) 10:20

И ещё раз хочу обратить ваше внимание на то, что использование файла ресурсов совершенно исключает редактирование строк пользователем!


Что и является основным недостатком данного способа!
Для хорошей программы пользователи могут самостоятельно локализовать ее и выслать кусок INI-шки автору. В случае с реестром все придется делать самому автору (а вряд ли автор знает все языки).

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


Никакой защиты это не даст - ресурсы тоже можно прекрасно редактировать. Если очень хочется, то достаточно окошко About сделать на английском (чтобы уж слишком просто не поменяли ссылки на автора).

Подобным способом (через INI-шки) локализуется громадное количество программ - и в основном как раз из-за простоты внесения изменений самими пользователями.

P.S я в основном локализацию хранил в MDB-шках - но просто мне так поудобней было (и интерфейс под это дело давно реализован), да и программы я пишу в основном для работы с базами, так что MDAC все одно там есть...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 10.08.2004 (Вт) 1:37

Andrey Fedorov писал(а):
Вот соответственно вопрос: а как этого не допустить? Ведь в каждой строке переименования не поставишь If str<>"nokey" then... И т.д. Т.е. надо если ключа нет, то кэпшн оставлять в неизменном состоянии.


А почему, собственно нет - что мешает-то?

Нормальный принцип - если нет строчки локализации на русском (к примеру) то вместо нее подставляется строка на английском. В результате то-же слово OK достаточно на русском просто не нужно описывать.


Ну ты сам представь себе: например, у меня 200 контролов которые надо локализовать, соотв. 200 строк считываний из ИНИ-файла, да если ещё и в каждой строке будет if ... then, то можно застрелиться будет :))...Я просто думал, может есть более рациональный способ, который позволит написать if...then один раз. :? :arrow:
И пусть в моих поступках не было логики...

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 10.08.2004 (Вт) 7:19

Ну ты сам представь себе: например, у меня 200 контролов которые надо локализовать, соотв. 200 строк считываний из ИНИ-файла, да если ещё и в каждой строке будет if ... then, то можно застрелиться будет )...


Ну кто-же так читает-то?

Всю локализацию ввобще удобней считать за раз в начале программы и поместить в коллекцию. Секцию INI-файла можно считать всего одной API-шной функцией (GetPrivateProfileSection). Так что тут все просто и быстро.

Ну а что где-то в цикле локализации контролов IF-Then стоять будет - это вообще не принципиально...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 10.08.2004 (Вт) 9:40

И вообще, если все грамотно продумать, никакой If...Then не нужен.
Один из примеров реализации:
Код: Выделить всё
Dim I As Long, ID As String, S As String
For I = 0 To frmMAIN.Controls.Count - 1
  If TypeOf frmMAIN.Controls(I) Is Label Then
    ID = frmMAIN.Controls(I).Tag
  ElseIf TypeOf frmMAIN.Controls(I) Is CommandButton Then
    ID = frmMAIN.Controls(I).Tag
  ElseIf TypeOf frmMAIN.Controls(I) Is Frame Then
    ID = frmMAIN.Controls(I).Tag
  ElseIf TypeOf frmMAIN.Controls(I) Is Menu Then
    ID = frmMAIN.Controls(I).Tag
  Else
    ID = vbNullString
  EndIf
  If Len(ID) > 0 Then
    S = GetLangItem("ru", ID)
    If Len(S) > 0 Then frmMAIN.Controls(I).Caption = S
  End If
Next I


GetLangItem - функция, возвращающая "локализованный" текст.
Lasciate ogni speranza, voi ch'entrate.

SBJocker
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 124
Зарегистрирован: 19.01.2004 (Пн) 16:57

Сообщение SBJocker » 12.08.2004 (Чт) 20:25

А я вот всё в ресурсы пихаю, и там есть очень приятная весчь, для каждого языка создаётся своя колонка и присваивается язык.

А vb сам читает строку из той колонки которая соответствует языковым настройкам компа...

Одна из колонок является дефолтной, чтоб было что писать если нет конкретной локализации...

А в хелпе проги нужно написать что переводы интерфейса приветствуются и адрес дать и пускай присылают кому надо...

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 13.08.2004 (Пт) 1:41

2 SBJocker: Все это конечно удобно, но как тебе её будут переводить, ведь юзеры не знают всех сообщений программы, сообщений ошибок.
Могут забыть несколько тултипов, кэпшенов описать...Очень гемморно в этом смыле.
И пусть в моих поступках не было логики...

soljen
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 69
Зарегистрирован: 06.05.2004 (Чт) 15:47
Откуда: Из темноты...

Сообщение soljen » 13.08.2004 (Пт) 9:46

Объясняю поподробнее!
Есть файл ресурсов. Структура такая: допустим первых 1000 строк, это строки на русском, 2-я 1000- на английском!
В программе мы смотрим на язык! Если к примеру в конфиге стоит 0, то мы при считывании ресурса, и подстановке его в Caption контрола (либо ещё куда-то) к номеру ресурса доюавляем 0, и тем самым получаем номер ресурса из 1-й тысячи, если в конфиге стоит 1000, то соответственно мы получим со второй тысячи!
Файл ресурсов не меняет юзер! "+"
Он компилится!
А вот смену интерфейса можно автоматически сделать через настройки в программе, при выборе языка меняется строка в конфиге, запускается батник, и перпестартовывает прогу.
Прога подтягивает число из конфига, и соответственно заполняет ресурся по всему проекту!
Тиха украинская ночь, но сало надо перепрятать...
(R)Jeka

Andrey Fedorov
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3287
Зарегистрирован: 21.05.2004 (Пт) 9:28
Откуда: Москва

Сообщение Andrey Fedorov » 13.08.2004 (Пт) 10:06

Есть файл ресурсов. Структура такая: допустим первых 1000 строк, это строки на русском, 2-я 1000- на английском!


Изначально кривой подход - по нормальному достаточно добавить столбец локализации.

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


Ну-ну, посмотрю я как будут выглядеть немецкие умляуты на русской Windows...
Фиг Вам! - Сказал Чебурашка, обгладывая Крокодила Гену...

soljen
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 69
Зарегистрирован: 06.05.2004 (Чт) 15:47
Откуда: Из темноты...

Сообщение soljen » 13.08.2004 (Пт) 13:56

Andrey Fedorov писал(а):Ну-ну, посмотрю я как будут выглядеть немецкие умляуты на русской Windows...


Да уж, посмотреть есть на что!
На украинском виндовозе немецкие и польские "умляуты" отображаются намано!
Про столбец.... оно конечно наверное лучше, но у нас так работает, а кто проектировал, даже не знаю! Мы архитектуру пока решили не трогать!
Тиха украинская ночь, но сало надо перепрятать...
(R)Jeka

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 14.08.2004 (Сб) 1:32

soljen писал(а):Файл ресурсов не меняет юзер! "+"
Он компилится!


Во-во, я и говорю :twisted: В этом вся и фигня.
Вот у тебя к примеру появился новый перевод проги, значит тебе надо все перекомпилировать, заново вывесить на сайт, а юзер, которому этот язык нужен, будет заново её качать :?: :twisted:
Глупость :arrow:
И пусть в моих поступках не было логики...

SBJocker
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 124
Зарегистрирован: 19.01.2004 (Пн) 16:57

Сообщение SBJocker » 14.08.2004 (Сб) 10:42

soljen писал(а):Объясняю поподробнее!
Файл ресурсов не меняет юзер! "+"
Он компилится!


Чтобы это стало минусом, нужно чтобы твоя прога была очень популярна по всему миру ( а это не так просто достичь). Так что этот минус довольно спорен...

Sanya Z
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 240
Зарегистрирован: 18.08.2003 (Пн) 3:15
Откуда: Москва

Сообщение Sanya Z » 16.08.2004 (Пн) 1:50

Дык щас почти все проги работают только с ИНИ и им подобными, а не с ресурсами.
И пусть в моих поступках не было логики...

SBJocker
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 124
Зарегистрирован: 19.01.2004 (Пн) 16:57

Сообщение SBJocker » 17.08.2004 (Вт) 20:53

Только Microsoft уже лет 10 борется с ини файлами, для того и реестр придумала...

А толку ноль :)

Так что использование ини-файлов это далеко не новомодный понт :) а скорее старомодный

SSecurity
Служба безопасности
Аватара пользователя
 
Сообщения: 1283
Зарегистрирован: 19.08.2003 (Вт) 1:11
Откуда: Россия, Мурманск

Сообщение SSecurity » 17.08.2004 (Вт) 23:46

Да, вот читаю я тут месаги все дело говорят :) только есть в файлах ресурсов очень удобна вещь - это возможность хранить картинки, если у тебя супер крутая прога, и пусть в ней даже есть супер ИНИ файл (который так уж достал MS), но хоть что ты делай, а юзер будет *KONFUSED* если прога работая под Дойтч, покажет русскую заставку, авторские права и прочие графические объекты :) (ето относится и к графическим бутонам) ...
Программист - это маленький Бог, а все его ошибки - это самостоятельные творения:)
Так задумано:)

След.

Вернуться в Visual Basic 1–6

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

    TopList  
cron