Вопрос: Могут ли программу переводить пользователи?
Добавлено: 13.02.05 15:50
Автор вопроса: П.С. | Web-сайт:psbatishev.narod.ru | ICQ: 225019134
Привет всем!
Подскажите, пожалуйста, какой есть самый лучший способ сделать в программе, написанной на Visual Basic 6
мультиязыковую поддержку. А еще чтобы пользователи разных стран могли сами переводить и вписывать перевод
в какой-нибудь диалог. Есть ли примеры кода? Или в VB6 уже заложено что-то подобное?
В свойство Tag помещаешь английское название контрола, в настройках хранишь текущий языковой файл. Затем при загрузке программы функциями работы с ini получаешь для каждого контрола его Caption, Text etc согласно его тегу. Например, у тебя есть чекбокс с анлийским названием "Update fields", это помещаешь в его свойство Tag, при загрузке проверяешь, какой установлен для программы языковой файл, например, lng_rus.txt, функциями работы с ini или аналогичными получаешь у него значение параметра "Update fields", допустим оно равно "Обновлять поля". Присваиваешь его, в зависимости от типа контрола либо Caption, либо Text, либо еще чему-нибудь. В результате каждый пользователь, знающий английский язык, сможет перевести такой файл и создать, таким образом, новый перевод для твоей программы.
Я в одной своей проге сделал так: при загрузке каждой формы из Form_Load вызовается функция GetLangToForm:
Public Declare Function GetPrivateProfileString& Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpszSection$, ByVal lpszKey$, ByVal lpszDefault$, ByVal lpszReturnBuffer$, ByVal cchReturnBuffer&, ByVal lpszFile$)
Public Sub GetLangToForm(ByRef bForm As Form)
Dim ob As Control
Dim bName As String
Dim obName As String
Dim TMP As String
'is Frame, XpB, Label, TextScr, OptionButton, CheckBox
'not image, TreeView, PivtureBox, Timer, List, ComboBox, imgButton
On Error Resume Next
bName = bForm.Name
For Each ob In bForm
obName = ob.Name
'здесь XpB и TextScr - типы UserControls
If TypeOf ob Is Label Or _
TypeOf ob Is Frame Or _
TypeOf ob Is OptionButton Or _
TypeOf ob Is CheckBox Or _
TypeOf ob Is XpB Or _
TypeOf ob Is TextScr Then
TMP = ""
TMP = ob.Index
If Len(TMP) > 0 Then obName = obName & "" & TMP & ""
TMP = ""
TMP = ob.Caption
If Len(TMP) > 0 Then ob.Caption = GetStr(bName, obName & ".Caption", TMP)
TMP = ""
TMP = ob.ToolTipText
If Len(TMP) > 0 Then ob.ToolTipText = GetStr(bName, obName & ".ToolTip", TMP)
End If
'  oEvents
Next
End Sub
Public Function GetStr(ByRef FormName As String, ByRef objName As String, ByRef DefaultStr As String, Optional ByRef lng As String) As String
Dim TMP55 As String * 1024
Dim ff As Long
If Len(lng) = 0 Then lng = "english"
If Len(lng) > 0 Then
Call GetPrivateProfileString(FormName, objName, DefaultStr, TMP55, 1024, App.Path & "\" & lng & ".lng"
ff = InStr(TMP55, vbNullChar)
If ff > 0 Then GetStr = Left$(TMP55, ff - 1)
Else
GetStr = DefaultStr
End If
End Function
в файлах *.lng (формат как в ini файлах) храняться переведенные свойства контролов (caption, ToolTip). У контролов на форме можно задать свойства caption и tooltip на английском языке (на случай если языковые файлы будут утерены).
По сравнению со способом Sharp'a тут не надо исполдьзовать дополнительные свойства кнтрола (tag)
Private Declare Function GetUserDefaultLangID Lib "kernel32" () As Integer
Private Declare Function VerLanguageName Lib "kernel32" Alias "VerLanguageNameA" (ByVal wLang As Long, ByVal szLang As String, ByVal nSize As Long) As Long
Private Const lngFileData As String = "lngFileData"
'--------------------------------------------------------------------------------
' Проект : OfflineClient
' Процедура : ID2Name
' Описание : То же самое что и VerLanguageName, но для VB поудобней будет
' Кем создан : SNE
' Дата-Время : 15.11.2004-0:35:17
'
' Параметры : lngID - ID языка название которого хочется узнать
'--------------------------------------------------------------------------------
Private Function ID2Name(ByVal lngID As Long) As String
ID2Name = VBA.String$(&H100, 0&
ID2Name = VBA.Left$(ID2Name, VerLanguageName(GetUserDefaultLangID, ID2Name, VBA.Len(ID2Name)))
End Function
'--------------------------------------------------------------------------------
' Проект : OfflineClient
' Процедура : GetDefaultLanguage
' Описание : Получение язака по умолчанию на данной машине
' Кем создан : SNE
' Дата-Время : 15.11.2004-0:23:24
'--------------------------------------------------------------------------------
Public Function GetDefaultLanguage() As String
GetDefaultLanguage = ID2Name(GetUserDefaultLangID)
End Function
'--------------------------------------------------------------------------------
' Проект : OfflineClient
' Процедура : GetLngFilePathByName
' Описание : Получение пути к файлу по имени языка
' Кем создан : SNE
' Дата-Время : 15.11.2004-0:02:30
'
' Параметры : sName - Название языка
'--------------------------------------------------------------------------------
Public Function GetLngFilePathByName(ByRef sName As String) As String
Dim sBuffer As String
sBuffer = VBA.Dir(clPath.sLngPath & "*.lng"
Do Until sBuffer = vbNullString
If sName = ID2Name(mIniEx.GetDword(clPath.sLngPath & sBuffer, lngFileData, "ID") Then
GetLngFilePathByName = clPath.sLngPath & sBuffer
Exit Do
End If
sBuffer = VBA.Dir()
Loop
End Function
'--------------------------------------------------------------------------------
' Проект : OfflineClient
' Процедура : EnumLang
' Описание : Заполнение менюшки-списка языков данными
' Кем создан : SNE
' Дата-Время : 15.11.2004-0:03:10
'
' Параметры : mnulng - Менюшка
'--------------------------------------------------------------------------------
Public Function EnumLanguages(ByRef MnuLng As Object) As Integer
Dim sBuffer As String
sBuffer = VBA.Dir(clPath.sLngPath & "*.lng"
Do Until sBuffer = vbNullString
With MnuLng(MnuLng.UBound)
.Tag = clPath.sLngPath & sBuffer
.Caption = ID2Name(mIniEx.GetDword(clPath.sLngPath & sBuffer, lngFileData, "ID")
.Checked = IIf(MnuLng(MnuLng.UBound).Caption = clSettings.sLanguage, True, False)
.Enabled = True
End With
sBuffer = VBA.Dir()
If Not sBuffer = vbNullString Then
Call Load(MnuLng(MnuLng.UBound + vbNull))
End If
Loop
End Function
'--------------------------------------------------------------------------------
' Проект : OfflineClient
' Процедура : GetLngStr
' Описание : Функция возвращает текстовую строку на каком-либо языке
' Кем создан : SNE
' Дата-Время : 08.11.2004-12:55:48
'--------------------------------------------------------------------------------
Public Function GetLngStr(ByRef sKey As String, _
Optional ByRef sName As String = "General" As String
GetLngStr = mIniEx.GetValue(clPath.sLngFileName, sName, sKey, vbNullString)
End Function
' Возвращает данные о том: массив ли это элементов
Private Function isArray(Element As Object) As Boolean
On Error GoTo err
If Element.Index + vbNull Then isArray = True
err:
End Function
' Придумано 24.10.02, вполне удачна, на мой взгляд (Переделана 02.03.03) -= Statist v1.3 =-
'--------------------------------------------------------------------------------
' Проект : OfflineClient
' Процедура : SetLng
' Описание : Автоматическая локализация элементов на форме
' Кем создан : SNE
' Дата-Время : 15.11.2004-1:01:26
'
' Параметры : Form - Форма
'--------------------------------------------------------------------------------
Public Sub SetLng(Form As Form)
On Error GoTo err
Dim i_il As Control
Dim sBuffer As String, sKey As String
sBuffer = mIniEx.GetValue(clPath.sLngFileName, Form.name, "Caption"
If Not sBuffer = vbNullString Then Form.Caption = sBuffer
For Each i_il In Form
If isArray(i_il) Then
sKey = "" & i_il.Index & ""
Else
sKey = vbNullString
End If
sBuffer = mIniEx.GetValue(clPath.sLngFileName, Form.name, i_il.name & sKey & ".Caption"
If Len(sBuffer) Then i_il.Caption = sBuffer
sBuffer = mIniEx.GetValue(clPath.sLngFileName, Form.name, i_il.name & sKey & ".ToolTipText"
If Len(sBuffer) Then i_il.ToolTipText = sBuffer
Next
Set i_il = Nothing
Exit Sub
err:
End Sub
lng файл:
[lngFileData]
ID = 1049
[frmMain]
Caption = Офф-лайн клиент для форума (VB6)
mnuFile.Caption = Файл
mnuChangeDB.Caption = Открыть другую БД
mnuExit.Caption = Выход
mnuVBNet.Caption = VBnet
.................
Основная маза моего способа состоит в том, что переводчику не надо догадываться, какой надписи соответствует mnuChangeDB.Caption, он может просто перевести английский текст, написанный справа.