VI-893
28 Giao di n ng th h tr đa ng
Các b n đã đ c h ng d n đ thi t l p l p đ i t ng BienDich ch ng 16 đ h tr cho nh ng ph n
m m đa ngôn ng Trong ch ng này, các b n s đ c h ng d n đ thi t k và phát tri n k thu t h
tr đa ngôn ng có th áp d ng cho nh ng ph n m m có giao di n Windows, và nh ng ph n m m m ng
ASP.NET dùng web-forms
VS c ng h tr đa ngôn ng cho các trình án v i ph ng pháp dùng nh ng t p tin tài nguyên (resource
file) có n i ti p ng m c đ nh là *.resx Nh ng t p tin này đ c biên l p và đ a vào linh ki n, tr thành
m t ph n c a lý l ch d li u (metadata) Ngoài ra, khi mu n dùng nh ng d li u đ c l u gi trong t p
tin tài nguyên, các b n ph i quy chi u nh ng không gian tên nh System.Globalization, System.Resource,
System.Reflection, và dùng nh ng l p đ i t ng thu c nh ng không gian tên trên đ có th l y v nh ng
chu i ký t có ngôn ng mu n dùng
Tuy nhiên, ch ng sách này không h ng d n các b n v ph ng th c h tr đa ngôn ng ph c t p c a
VS Các b n s đ c h ng d n đ dùng m t t p tin XML duy nh t đ h tr k thu t đa ngôn ng L i
đi m c a ph ng th c này, là t p tin XML có th đ c thay đ i sau khi ph n m m đã đ c phát hành
Do đó, nh ng ngôn ng m i có th đ c đ a thêm vào t p tin XML b t c lúc nào Thí d nh , các b n
có m t ph n m m ng d ng đã đ c phát tri n đ h tr Anh ng và Vi t ng Sau khi ph n m m đã
đ c phát hành, các b n có yêu c u h tr cho Pháp ng Các b n ch c n g i g i m t t p tin XML có h
tr Pháp ng t i khách hàng, thì l p t c, ph n m m c a các b n s có th hi n th Pháp ng trên nh ng
giao di n ng th
Tìm hi u v l p đ i t ng Control
Nh các b n đã đ c h ng d n, t t c nh ng l p đ i t ng NET Framework đ u th a k tr c ti p ho c
gián ti p t l p đ i t ng n n System.Object L p đ i t ng Control, thu c không gian tên
System.Windows.Forms, là m t l p đ i t ng trong NET Framework Do đó, l p Control c ng đ c
th a k gián ti p t l p đ i t ng System.Object nh b t c m t l p đ i t ng nào khác
L p đ i t ng Control h tr 2 ch c n ng kéo và th Do đó, t t c nh ng l p đ i t ng có giao di n ng
th thu c không gian tên System.Windows.Forms có th kéo và th xu ng m t l p đ i t ng Form
khung thi t k t đ u đ c th à k t l p Control
Ng c l i, t t c nh ng l p đ i t ng thu c không gian tên System.Windows.Form không th kéo và th
xu ng khung thi t k , là nh ng l p đ i t ng không đ c th a k t l p Control Thí d nh l p đ i
t ng System.Windows.Forms.ToolStripMenuItem, tuy có giao di n ng th , nh ng không thu c v l p
đ i t ng Control Do đó, các b n không th kéo và th m t đ i t ng c a l p
System.Windows.Forms.ToolStripMenuItem xu ng khung thi t k M c dù th , sau khi kéo và th m t
đ i t ng MenuStrip xu ng khung thi t k , các b n có th t o nh ng thu c đ n, là nh ng đ i t ng l p
ToolStripMenuItem
D ng l p đ i t ng Control có trên 100 thành viên Nh ng trong ph m vi h tr k thu t đa ngôn ng ,
chúng ta ch l u ý t i 2 thành viên c a d ng l p này: đó là thu c tính Controls, và thu c tính Text Thu c
Trang 2VI-894 L p trình v i giao di n Windows | Quang- t
tính Text đ c dùng đ l u gi m t chu i ký t cho nh ng đ i t ng l p Control thu c v m t khung
trình (Form) Do đó, tr ng tâm c a k thu t h tr đa ngôn ng , là làm sao có th phiên d ch chu i ký t
đ c l u gi trong thu c tính Text, và c p nh t chu i ký t này v i m t chu i ký t đã đ c phiên d ch
Tìm hi u v thành viên Controls trong l p đ i t ng Form
L p đ i t ng Form đ c th à k gián ti p t l p đ i t ng Control (do đó, đ c th a h ng thành viên
Controls và Text) Thành viên Controls thu c d ng ControlCollection, đ c dùng đ l u tr m t t p h p
nh ng đ i t ng l p Control i m quan tr ng nh t, là t t c nh ng đ i t ng l p Control đ c l u gi
trong thành viên Controls đ u đ c hi n th trên khung trình, ngo i tr nh ng đ i t ng đã đ c d u đi
b ng cách g i hàm Control.Hide() t ng đ i t ng l p
Do đó, trên ph ng di n k thu t ng th , m t khung trình thu c l p đ i t ng Form, là m t đ i t ng
l p Control g m có nh ng đ i t ng l p Control có nh ng đ i t ng l p Control/Object , nh minh h a
d i đây:
Minh-h a 28-1: C u trúc c n b n c a m t khung trình (Form)
D a theo c u trúc trên, các b n có th vi t mã ngu n đ duy t qua t t c nh ng đ i t ng có giao di n
ng th trong m t khung trình r t d dàng, b t đ u t thành viên c a Controls c a khung trình, nh sau:
privatestaticvoid DuyetForm()
Trang 3VI-895
2 hàm m u trên đ c vi t đ duy t qua t t c nh ng đ i t ng l p Control Hàm DuyetForm() kh i t o
m t đ i t ng l p Form có d ng frmQLDoanhNghiep Sau đó g i hàm DuyetControls() v i tham s là
đ i t ng l p Form đ c ép d ng qua d ng l p Control Hàm DuyetControls() là m t hàm l p
(recursive method), đ c dùng đ duy t qua t t c nh ng đ i t ng thu c d ng Control đ c l u gi
trong thành viên Controls Mã ngu n đã đ c vi t r t đ n gi n, nh ng vô cùng hi u qu
Và, n u các b n có th duy t qua t t c các đ i t ng có giao di n ng th thu c d ng l p Control nh đã
th c hi n trong hàm m u DuyetControls() trên, d nhiên các b n có th g i hàm BienDich.Translate() đã
đ c phát tri n trong linh ki n UtilCommon.dll đ phiên d ch nh ng chu i ký t l u tr trong thu c tính
Các b n hãy t o m t l p đ i t ng m i có d ng t nh, có tên là FormExt L p FormExt s có 3 hàm n i
r ng cho l p đ i t ng Form, đ c vi t nh sau:
publicstaticclassFormExt
{
publicstaticBienDich bienDich = newBienDich();
publicstaticvoid LoadDictionary(thisForm frm, string xmlDictionaryFile, string language)
string formName = frm.Name.Substring(1 + frm.Name.LastIndexOf('.', 0));
Translate(formName,(Control)frm); // Ph i ép d ng, n u không s l p t i hàm này
}
}
D ng l p FormExt đ nh ngh a thành viên bienDich, thu c d ng l p BienDich Thành viên này đ c kh i
t o khi m t đ i t ng l p Form đ u tiên c a m t ph n m m đ c kh i t o Thí d nh , n u các b n kh i
Trang 4VI-896 L p trình v i giao di n Windows | Quang- t
đ ng ph n m m QLDoanhNghiep, khung trình đ u tiên đ c kh i t o thu c v d ng l p
frmQLDoanhNghiep Khi đ i t ng l p frmQLDoanhNghiep đ c kh i t o, thành viên bienDich c ng
s đ c kh i t o i m quan tr ng c n l u ý là, cho dù ph n m m QLDoanhNghiep có r t nhi u khung
trình khác nhau, nh ng ch có m t đ i t ng l p BienDich đ c kh i t o, vì thành viên bienDich thu c
v d ng t nh
Hàm n i r ng LoadDictionary() có 3 tham s Vì là hàm n i r ng cho d ng l p Form, nên tham s đ u
tiên b t bu c ph i là m t tham s this thu c d ng Form Tham s th hai là tên c a t p tin XML v i
khuôn m u đã đ c n đ nh (xin tham kh o ch ng 16) Tham s cu i cùng là ký s c a ngôn ng th
hai, c ng là ngôn ng s đ c biên d ch qua t ngôn ng chính, và đ c hi n th trong nh ng giao di n
ng th
Ph n m m h tr đa ngôn ng ch nên g i hàm LoadDictionary() m t l n duy nh t khi khung trình đ u
tiên đ c kh i t o Tuy nhiên, n u hàm này đ c g i l n th hai, không có chuy n gì s x y ra, và giòng
v n hành s l p t c quay v hàm g i, vì hàm LoadDictionary() trong l p đ i t ng BienDich ch t i t p
tin XML lên b nh m t l n duy nh t nh sau:
publicvoid LoadDictionary(string xmlDictionaryFile, string Language)
string msg = String.Format("Could not load file {0}", xmlDictionaryFile);
thrownewException(msg, xmlError);
}
}
Nh đã th y trên, hàm LoadDictionary() th m tra tr ng xmlDic tr c khi ti p n i v i nh ng cú pháp
dùng đ t i t p tin XML lên b nh N u xmlDic không có giá tr = null, có ngh a là t p tin XML đã đ c
t i lên b nh , giòng v n hành s l p t c quay tr v hàm g i
Hàm n i r ng th 2 là hàm SaveDictionary() Hàm này đ c g i đ n i ti p hóa ngu n d li u XML t
b nh xu ng t p tin đ c ch đ nh qua tham s Các b n s đ c h ng d n tham kh o v công d ng và
m c đích c a hàm này trong nh ng ph n k ti p
Hàm n i r ng th 3 là hàm Translate() ây là hàm ch y u dùng cho vi c phiên d ch Hàm này ch nên
g i m t l n duy nh t cho m t khung trình a đi m thích h p nh t đ g i hàm này n m trong ph m vi
c a s tác Form.Load() S tác Form.Load() đ c kích ho t 1 l n duy nh t khi m t khung trình đ c
Trang 5VI-897
hi n th l n đ u tiên Khi s tác Form.Load() đ c kích ho t, đ i t ng d ng l p Form đã qua giai đo n
kh i t o, t t c nh ng đ i t ng d ng Control thu c v khung trình đ u đã đ c thi t l p
Hàm n i r ng Form.Translate() duy t qua t t c nh ng đ i t ng l p Control thu c v khung trình, và
g i hàm BienDich.Translate() đ phiên d ch t t c nh ng chu i ký t đ c hi n th trên khung trình D
nhiên, hàm này tuy t đ i không phiên d ch nh ng chu i ký t thu c quy n s h u c a ng i x d ng
(ch ng h n nh nh ng chu i ký t trong thu c tính Text c a đ i t ng l p TextBox), vì đó là nh ng chu i
ký t thu c v d li u
FormExt.Translate() c ng là m t ch ng hàm g m có 4 hàm, v i m t hàm n i r ng duy nh t có d ng
chung 3 hàm còn l i đ c phong kín v i d ng t Nh các b n đã th y ph n trên, hàm n i r ng
FormExt.Translate() ch đ n gi n có 2 giòng mã ngu n nh sau:
string formName = frm.Name.Substring(1 + frm.Name.LastIndexOf('.', 0));
Translate(formName,(Control)frm); // Ph i ép d ng, n u không s l p t i hàm này
Giòng mã ngu n th nh t t o m t chu i ký t đ l u gi tên c a d ng l p thu c v khung trình Thí d
nh , n u hàm Translate() đ c g i t đ i t ng l p frmQLDoanhNghiep, chu i ký t s có giá tr =
”frmQLDoanhNghiep” N u các b n còn nh nh ng gì đã đ c trong ch ng 16, thì tên d ng l p c a m t
khung trình s đ c dùng làm th XML đ có th giúp cho vi c tìm ki m d li u trong ngu n d li u
XML đ c mau chóng h n
Giòng mã ngu n th hai g i hàm Translate() có tham s thu c d ng l p Control Do đó, khi đ a đ i
t ng l p Form vào tham s , đ i t ng này đ c ép qua d ng Control
Trang 6VI-898 L p trình v i giao di n Windows | Quang- t
foreach (ToolStripItem mnuItem in ((MenuStrip)ctrl).Items)
Hàm Translate() có tham s thu c d ng Control trên, là kh i đi m c a nh ng thao tác x lý cho ch c
n ng phiên d ch c a m t khung trình ây là m t hàm l p đ c dùng đ duy t qua t t c nh ng đ i t ng
thu c d ng Control trong m t khung trình L u ý là khi m t đ i t ng Control thu c d ng MenuStrip
ho c DataGridView, là nh ng d ng có l u gi nh ng giao di n ng th không thu c d ng l p Control,
nên ph i có nh ng x lý khác bi t
Kh i mã ngu n trong ph m vi x lý cho DataGridView ch y u dành cho vi c biên d ch nh ng chu i ký
t l u tr trong thu c tính ColumnHeader c a nh ng đ i t ng d ng DataGridViewColumn Nh ng
chu i ký t này c ng có th đ c phiên d ch tr c ti p khi nh ng đ i t ng DataGridViewColumn đ c
kh i t o Do đó, kh i mã ngu n này đ c vi t đây nh m m c đích h ng d n các b n tham kh o v
nh ng ph ng cách duy t xu ng nh ng đ i t ng d ng Object đ c l u gi trong m t đ i t ng d ng
Control, thay vì có m c đích th c d ng
Riêng kh i mã ngu n trong ph m vi x lý cho MenuStrip là m t tr ng h p x lý đ c bi t MenuStrip là
m t trình đ n thu c d ng Control có th kéo và th xu ng m t khung trình i t ng MenuStrip l u
gi m t t p h p nh ng đ i t ng có d ng l p ToolStripItem trong thu c tính Items Và nh ng đ i t ng
thu c d ng ToolStripItem này có thu c tính DropDownItems, đ c dùng đ l u gi m t t p h p nh ng
đ i t ng c ng thu c d ng l p ToolStripItem Do đó, khi duy t qua nh ng đ i t ng l p ToolStripItem
trong đ i t ng l p MenuStrip, thao tác x lý g i hàm Translate(ToolStripItem), là m t hàm l p, đ c
dùng đ duy t xu ng t t c nh ng thu c đ n thu c v m t trình đ n
Trang 7VI-899
mnu.Text = BienDich.Translate("Menu",mnu.Text);
}
Hàm Translate(ToolStripItem), nh đã đ c p đ n ph n trên, đ c dùng đ x lý phiên d ch cho nh ng
thu c đ n thu c v m t trình đ n ây là m t hàm l p có mã ngu n r t đ n gi n v i vòng l p foreach()
đ c dùng đ duy t qua nh ng thu c đ n trong DropDownItems i m đ c bi t là giòng mã ngu n
cu i cùng, thay vì g i hàm Translate(Object) đ phiên d ch chu i ký t cho thu c đ n, hàm này tr c ti p
caseClassType.System_Windows_Forms_Button:
caseClassType.System_Windows_Forms_CheckBox:
caseClassType.System_Windows_Forms_Form:
caseClassType.System_Windows_Forms_Label:
caseClassType.System_Windows_Forms_RadioButton:
caseClassType.System_Windows_Forms_TabPage:
((Control)doiTuong).Text = BienDich.Translate(formName, ((Control)doiTuong).Text);
break;
//Nh ng d ng l p th a k t ToolStripItem
caseClassType.System_Windows_Forms_ToolStripItem:
caseClassType.System_Windows_Forms_ToolStripMenuItem:
((ToolStripItem)doiTuong).Text = BienDich.Translate("Menu", ((ToolStripItem)doiTuong).Text);
break;
//Nh ng d ng l p th a k t ColumnHeader
caseClassType.System_Windows_Forms_ColumnHeader:
((ColumnHeader)doiTuong).Text = BienDich.Translate("CSDL", ((ColumnHeader)doiTuong).Text);
Hàm Translate(string,Object) là hàm cu i cùng trong ch ng hàm Translate() Hàm này nh n tham s có
d ng Object, và g i hàm DangDuLieu() đ xác đ nh d ng l p đ i t ng c a tham s đoiTuong Sau khi
đã xác đ nh đ c d ng l p c a tham s , t khóa switch{}đ c dùng đ x lý vi c phiên d ch d a theo
nh ng d ng l p khác nhau Chú thích và cú pháp vi t trong hàm th a đ đ chú gi i r t rõ ràng nh ng
thao tác x lý cho vi c phiên d ch cho đ i t ng nh n đ c qua tham s
Toàn b l p đ i t ng FormExt, v i nh ng hàm n i r ng cho d ng l p System.Windows.Forms.Form,
Trang 8VI-900 L p trình v i giao di n Windows | Quang- t
publicstaticBienDich bienDich = newBienDich();
publicstaticvoid LoadDictionary(thisForm frm, string xmlDictionaryFile, string language)
string formName = frm.Name.Substring(1 + frm.Name.LastIndexOf('.', 0));
Translate(formName, (Control)frm); // Ph i ép d ng, n u không s l p t i hàm này
Trang 9caseClassType.System_Windows_Forms_Button:
caseClassType.System_Windows_Forms_CheckBox:
caseClassType.System_Windows_Forms_Form:
caseClassType.System_Windows_Forms_Label:
caseClassType.System_Windows_Forms_RadioButton:
caseClassType.System_Windows_Forms_TabPage:
((Control)doiTuong).Text = BienDich.Translate(formName, ((Control)doiTuong).Text);
break;
//Nh ng d ng l p th a k t ToolStripItem
caseClassType.System_Windows_Forms_ToolStripItem:
caseClassType.System_Windows_Forms_ToolStripMenuItem:
((ToolStripItem)doiTuong).Text = BienDich.Translate("Menu", ((ToolStripItem)doiTuong).Text);
break;
//Nh ng d ng l p th a k t ColumnHeader
caseClassType.System_Windows_Forms_ColumnHeader:
((ColumnHeader)doiTuong).Text = BienDich.Translate("CSDL", ((ColumnHeader)doiTuong).Text);
break;
caseClassType.System_Windows_Forms_DataGridViewColumn:
((DataGridViewColumn)doiTuong).HeaderText = BienDich.Translate(formName,
Trang 10VI-902 L p trình v i giao di n Windows | Quang- t
if (ctrl isButton) dangDuLieu = ClassType.System_Windows_Forms_Button;
elseif (ctrl is System.Windows.Forms.CheckBox) dangDuLieu = ClassType.System_Windows_Forms_CheckBox;
elseif (ctrl is System.Windows.Forms.ColumnHeader) dangDuLieu =
ClassType.System_Windows_Forms_ColumnHeader;
elseif (ctrl is System.Windows.Forms.DataGridViewColumn) dangDuLieu =
ClassType.System_Windows_Forms_DataGridViewColumn;
elseif (ctrl is System.Windows.Forms.Form) dangDuLieu = ClassType.System_Windows_Forms_Form;
elseif (ctrl is System.Windows.Forms.Label) dangDuLieu = ClassType.System_Windows_Forms_Label;
elseif (ctrl is System.Windows.Forms.RadioButton) dangDuLieu = ClassType.System_Windows_Forms_RadioButton;
elseif (ctrl is System.Windows.Forms.TabPage) dangDuLieu = ClassType.System_Windows_Forms_TabPage;
elseif (ctrl is System.Windows.Forms.ToolStripItem) dangDuLieu = ClassType.System_Windows_Forms_ToolStripItem;
elseif (ctrl is System.Windows.Forms.ToolStripMenuItem) dangDuLieu =
L p đ i t ng BienDich là thành ph n ch y u h tr ch c n ng đa ngôn ng cho m t ph n m m Nh ng
hàm n i r ng cho d ng l p Form, khi tìm th y m t giao di n ng th , đ u g i hàm BienDich.Translate()
đ phiên d ch m t chu i ký t t Anh ng qua m t ngôn ng ch đ nh M i khi c n ph i hi n th m t
thông tin qua hàm MessageBox.Show(), ho c khi c n ph i phiên d ch b t c m t chu i ký t nào, hàm
BienDich.Translate() c ng có th đ c g i tr c ti p t b t c m t đ a đi m nào trong mã ngu n
D ng l p BienDich đ nh ngh a 3 thu c tính sau đây:
staticXmlDocument xmlDic = null;
staticbool isFileChanged = false;
staticstring CurrentLanguage = string.Empty;
Thu c tính xmlDic thu c d ng XmlDocument, đ c dùng đ l u gi ngu n d li u XML đ c t i lên t
m t t p tin XML có khuôn m u n đ nh, và có nh ng th <English> đ c l ng trong nh ng th Cha
M i th < English> có thu c tính Text đ c dùng đ l u gi m t chu i ký t Anh ng L ng trong th
< English> là m t hay nhi u th con M i th con l u gi m t chu i ký t đã đ c phiên d ch cho m t
ngôn ng khác, và tên c a nh ng th con này ch đ nh ngôn ng đã đ c phiên d ch Thu c tính xmlDic
Trang 11VI-903
thu c d ng t nh Cho nên ch có m t phiên b n c a xmlDic đ c l u gi trên b nh trong toàn b th i
gian v n hành c a m t ph n m m, không c n bi t ph n m m đó đã t o lên bao nhiêu đ i t ng l p
BienDich
Thu c tính th hai là thu c tính isFileChanged, thu c d ng t nh Thu c tính này có giá tr m c đ nh =
false Khi ngu n d li u xmlDic đ c thay đ i (đ c cho thêm nh ng th m i), thu c tính isFileChanged
s có giá tr = true
Thu c tính cu i cùng là CurrentLanguage Thu c tính này l u gi m t chu i ký t ng n đ i bi u cho
ngôn ng mà ph n m m đang h tr Chu i ký t này th ng có 2 đ n 3 ký t , là m t trong nh ng mã
ngôn ng nh VI cho Vi t ng , FR cho Pháp ng , CN cho Hoa ng , v.v , và đ c dùng làm tên cho
nh ng th con đ c l ng trong th <English>, thí d nh :
<English text="Do you want to exit the application?">
Hàm LoadDictionary() đ c dùng đ t i m t t p tin XML ch đ nh vào đ i t ng l p XmlDocument (qua
thu c tính xmlDic), đ c vi t nh sau:
publicvoid LoadDictionary(string xmlDictionaryFile, string Language)
string msg = String.Format("Could not load file {0}", xmlDictionaryFile);
thrownewException(msg, xmlError);
Trang 12VI-904 L p trình v i giao di n Windows | Quang- t
Hàm SaveDictionary() c ng là m t hàm r t đ n gi n Hàm này đ c g i đ n i ti p hóa ngu n d li u
l u gi trong thu c tính xmlDic vào m t t p tin XML ch đ nh Hàm này h tr cho vi c đ ng b hoá
m ch trình (v i lock()) Cho nên, m t ph n m m đa m ch can có th g i hàm này an toàn mà không s
nh ng m ch trình có th xung đ t v i nhau t o lên nh ng l i ngo i l Hàm SaveDictionary() đ c vi t
XmlTextWriter xmlWriter = newXmlTextWriter(xmlDictionaryFile, Encoding.UTF8);
xmlWriter.Formatting = Formatting.Indented;
Khi mu n n i ti p hóa m t ngu n d li u thu c d ng XmlDocument, các b n c n ph i dùng m t đ i
t ng l p h tr cho vi c n i ti p hóa Trong hàm trên, đ i t ng l p XmlTextWriter đã đ c dùng Có
2 đi m đáng l u ý trong vi c dùng XmlTextWriter Th nh t là phong ch đ c áp đ t theo khuôn th c
UTF-8, là khuôn th c có th h tr cho đa ngôn ng Th hai là khuôn m u (Formatting) c a ngu n d
li u đ c áp đ t v i Formatting.Indented V i khuôn m u này, nh ng th XML đ c t đ ng th t l
(indentation) và xu ng giòng khi n i ti p hóa xu ng t p tin
Hàm TranslateFromXPath() và ch ng hàm Translate()
Các b n ch có th g i hàm TranslateFromXPath() n u có ki n th c v XPath, đ có th t o m t chu i
l nh XPath đ dùng làm tham s khi g i hàm này Tuy nhiên hàm này đ c đ nh d ng t , cho nên ch có
th g i trong ph m vi c a l p đ i t ng BienDich L p đ i t ng BienDich cung c p ch ng hàm
Translate() có d ng chung đ h tr cho ch c n ng phiên d ch m t chu i ký t Ch ng hàm này t o m t
chu i l nh XPath, và g i hàm TranslateFromXPath() D i đây là mã ngu n cho c 3 hàm:
publicstaticstring Translate(string formName, string msg)