Silverlight 2.0 的波斯语 (Farsi) 语言支持
Silverlight 2.0 的波斯语 (Farsi) 语言支持
引言
由于 Silverlight 2.0 缺乏对从右到左 (RTL) 语言(例如波斯语/Farsi)的支持,因此 RTL 文本在 Silverlight 中无法正确呈现。此项目是一个辅助库,允许在 Silverlight 2.0 中使用波斯语文本。
源代码托管在 CodePlex 上,作为一个开放源代码项目,可在此处获得。
代码描述
PersianCharacter.cs
类用于定义波斯语字符映射。
internal class PersianCharacter
{
public PersianCharacter(string characterName, bool noLastAppend, int
startChar, int middleRightSideBoundedChar, int
middleLeftSideBoundedChar, int middleTwoSideBoundedChar, int
endingBoundedChar, int endingChar)
{
CharacterName = characterName;
NoLastAppend = noLastAppend;
StartChar = startChar;
MiddleRightSideBoundedChar = middleRightSideBoundedChar;
MiddleLeftSideBoundedChar = middleLeftSideBoundedChar;
MiddleTwoSideBoundedChar = middleTwoSideBoundedChar;
EndingBoundedChar = endingBoundedChar;
EndingChar = endingChar;
}
private string _CharacterName = "";
public string CharacterName
{
get
{
return _CharacterName;
}
set
{
_CharacterName = value;
}
}
private bool _NoLastAppend = false;
public bool NoLastAppend
{
get
{
return _NoLastAppend;
}
set
{
_NoLastAppend = value;
}
}
private int _StartChar = 0;
public int StartChar
{
get
{
return _StartChar;
}
set
{
_StartChar = value;
}
}
private int _MiddleRightSideBoundedChar = 0;
public int MiddleRightSideBoundedChar
{
get
{
return _MiddleRightSideBoundedChar;
}
set
{
_MiddleRightSideBoundedChar = value;
}
}
private int _MiddleLeftSideBoundedChar = 0;
public int MiddleLeftSideBoundedChar
{
get
{
return _MiddleLeftSideBoundedChar;
}
set
{
_MiddleLeftSideBoundedChar = value;
}
}
private int _MiddleTwoSideBoundedChar = 0;
public int MiddleTwoSideBoundedChar
{
get
{
return _MiddleTwoSideBoundedChar;
}
set
{
_MiddleTwoSideBoundedChar = value;
}
}
private int _EndingBoundedChar = 0;
public int EndingBoundedChar
{
get
{
return _EndingBoundedChar;
}
set
{
_EndingBoundedChar = value;
}
}
private int _EndingChar = 0;
public int EndingChar
{
get
{
return _EndingChar;
}
set
{
_EndingChar = value;
}
}
}
PersianMaker.cs
类负责格式化波斯语字符串的过程。它有五个方法,我将在这里简要讨论。
首先,我们定义所有波斯语字符,并将它们添加到 CharacterMap
列表中。大约有 40 个字符,即使实际的波斯语字符数少于 40 个。有些阿拉伯字符现在在波斯语写作中使用。使用 PersianCharacter
类的对象填充字符映射后,就可以使用了。感谢 LINQ 对 LINQ to Objects 的支持,因为它减少了循环次数。
IsPersianCharacter
方法用于检查指定的字符是否属于波斯语字符映射。 这将通过查询 CharacterMap
列表来完成。
IsNoLastAppendCharacter
检查指定的字符是否为不能在末尾追加字符的波斯语字符,例如 Je(ژ) 或 Re (ر)。
ReverseString
将接受一个字符串,然后将其反转。我们需要此方法,因为我们应该反转字符串才能在 Silverlight 中正确显示,因为缺少从右到左的支持。
ToPersianString
是这个类的核心,因为它接受原始(未格式化)的文本,并生成可以在 Silverlight 内容中正确显示的字符串。此方法逐个字符地迭代文本,以正确地连接波斯语字符。
ToPersian
首先按空格分隔单词,然后将它们传递给 ToPersianString
。然后它连接单词并返回可以在 Silverlight 2.0 内容中正确显示的最终字符串。
public class PersianMaker
{
// Persian character map
private List<PersianCharacter> CharacterMap;
public PersianMaker()
{
CharacterMap = new List<PersianCharacter>();
#region ABaKolah آ
CharacterMap.Add(new PersianCharacter("ABaKolah", true,
0x622, 0x622, 0xfe82, 0xfe81, 0xfe82, 0xfe81));
# endregion
#region Alef ا
CharacterMap.Add(new PersianCharacter("Alef", true, 0x627,
0x627, 0xfe8e, 0xfe8d, 0xfe8e, 0xfe8d));
# endregion
#region AlefWithHamzeAbove أ
CharacterMap.Add(new PersianCharacter("AlefWithHamzeAbove",
true, 0x623, 0x623, 0xfe84, 0xfe83, 0xfe84, 0xfe83));
# endregion
#region AlefWithHamzeBelow إ
CharacterMap.Add(new PersianCharacter("AlefWithHamzeBelow",
true, 0x625, 0x625, 0xfe88, 0xfe87, 0xfe88, 0xfe87));
# endregion
#region Hamze ء
CharacterMap.Add(new PersianCharacter("Hamze", true,
0x621, 0x621, 0xfe80, 0xfe80, 0xfe80, 0xfe7f));
# endregion
#region Be ب
CharacterMap.Add(new PersianCharacter("Be", false,
0x628, 0x628, 0xfe90, 0xfe91, 0xfe92, 0xfe8f));
# endregion
#region Pe پ
CharacterMap.Add(new PersianCharacter("Pe", false,
0x67e, 0x67e, 0xfb57, 0xfb58, 0xfb59, 0xfb56));
# endregion
#region Te ت
CharacterMap.Add(new PersianCharacter("Te", false,
0x62a, 0x62a, 0xfe96, 0xfe97, 0xfe98, 0xfe95));
# endregion
#region Theh ث
CharacterMap.Add(new PersianCharacter("Theh", false,
0x62b, 0x62b, 0xfe9a, 0xfe9b, 0xfe9c, 0xfe99));
# endregion
#region Jeem ج
CharacterMap.Add(new PersianCharacter("Jeem", false,
0x62c, 0x62c, 0xfe9e, 0xfe9f, 0xfea0, 0xfe9d));
# endregion
#region Che چ
CharacterMap.Add(new PersianCharacter("Che", false,
0x686, 0x686, 0xfb7b, 0xfb7c, 0xfb7d, 0xfb7a));
# endregion
#region Hah ح
CharacterMap.Add(new PersianCharacter("Hah", false,
0x62d, 0x62d, 0xfea2, 0xfea3, 0xfea4, 0xfea1));
# endregion
#region Kheh خ
CharacterMap.Add(new PersianCharacter("Kheh", false,
0x62e, 0x62e, 0xfea6, 0xfea7, 0xfea8, 0xfea5));
# endregion
#region Dal د
CharacterMap.Add(new PersianCharacter("Dal", true,
0x62f, 0x62f, 0xfeaa, 0xfea9, 0xfeaa, 0xfea9));
# endregion
#region Zal ذ
CharacterMap.Add(new PersianCharacter("Zal", true,
0x630, 0x630, 0xfeac, 0xfeab, 0xfeac, 0xfeab));
# endregion
#region Re ر
CharacterMap.Add(new PersianCharacter("Re", true, 0x631,
0x631, 0xfeae, 0xfead, 0xfeae, 0xfead));
# endregion
#region Ze ز
CharacterMap.Add(new PersianCharacter("Ze", true,
0x632, 0x632, 0xfeb0, 0xfeaf, 0xfeb0, 0xfeaf));
# endregion
#region Je ژ
CharacterMap.Add(new PersianCharacter("Je", true,
0x698, 0x698, 0xfb8b, 0xfb8a, 0xfb8b, 0xfb8a));
# endregion
#region Seen س
CharacterMap.Add(new PersianCharacter("Seen", false,
0x633, 0x633, 0xfeb2, 0xfeb3, 0xfeb4, 0xfeb1));
# endregion
#region Sheen ش
CharacterMap.Add(new PersianCharacter("Sheen", false,
0x634, 0x634, 0xfeb6, 0xfeb7, 0xfeb8, 0xfeb5));
# endregion
#region Sad ص
CharacterMap.Add(new PersianCharacter("Sad", false,
0x635, 0x635, 0xfeba, 0xfebb, 0xfebc, 0xfeb9));
# endregion
#region Zad ض
CharacterMap.Add(new PersianCharacter("Zad", false,
0x636, 0x636, 0xfebe, 0xfebf, 0xfec0, 0xfebd));
# endregion
#region Ta ط
CharacterMap.Add(new PersianCharacter("Ta", false,
0x637, 0x637, 0xfec2, 0xfec3, 0xfec4, 0xfec1));
# endregion
#region Za ظ
CharacterMap.Add(new PersianCharacter("Za", false,
0x638, 0x638, 0xfec6, 0xfec7, 0xfec8, 0xfec5));
# endregion
#region Ein ع
CharacterMap.Add(new PersianCharacter("Ein", false,
0x639, 0xfeca, 0xfeca, 0xfecb, 0xfecc, 0xfec9));
# endregion
#region Ghein غ
CharacterMap.Add(new PersianCharacter("Ghein", false,
0x63a, 0x63a, 0xfece, 0xfecf, 0xfed0, 0xfecd));
# endregion
#region Fe ف
CharacterMap.Add(new PersianCharacter("Fe", false,
0x641, 0x641, 0xfed2, 0xfed3, 0xfed4, 0xfed1));
# endregion
#region Ghaf ق
CharacterMap.Add(new PersianCharacter("Ghaf", false,
0x642, 0x642, 0xfed6, 0xfed7, 0xfed8, 0xfed5));
# endregion
#region kaf ک
CharacterMap.Add(new PersianCharacter("kaf", false,
0x6a9, 0x6a9, 0xfeda, 0xfedb, 0xfedc, 0xfed9));
# endregion
#region Gaf گ
CharacterMap.Add(new PersianCharacter("Gaf", false,
0x6af, 0x6af, 0xfb93, 0xfb94, 0xfb95, 0xfb92));
# endregion
#region Lam ل
CharacterMap.Add(new PersianCharacter("Lam", false,
0x644, 0x644, 0xfede, 0xfedf, 0xfee0, 0xfedd));
# endregion
#region Meem م
CharacterMap.Add(new PersianCharacter("Meem", false,
0x645, 0x645, 0xfee2, 0xfee3, 0xfee4, 0xfee1));
# endregion
#region Noon ن
CharacterMap.Add(new PersianCharacter("Noon", false,
0x646, 0x646, 0xfee6, 0xfee7, 0xfee8, 0xfee5));
# endregion
#region Vav و
CharacterMap.Add(new PersianCharacter("Vav", true, 0x648,
0x648, 0xfeee, 0xfeed, 0xfeee, 0xfeed));
# endregion
#region VavBaHamze ؤ
CharacterMap.Add(new PersianCharacter("VavBaHamze", true,
0x624, 0x624, 0xfe86, 0xfe85, 0xfe86, 0xfe85));
# endregion
#region Heh ه
CharacterMap.Add(new PersianCharacter("Heh", false,
0x647, 0x647, 0xfeea, 0xfeeb, 0xfeec, 0xfee9));
# endregion
#region TehMarbuta ة
CharacterMap.Add(new PersianCharacter("TehMarbuta",
true, 0x629, 0x629, 0xfe94, 0xfe93, 0xfe93, 0xfe93));
# endregion
#region Ye ی
CharacterMap.Add(new PersianCharacter("Ye", false,
0x6cc, 0x6cc, 0xfef0, 0xfef3, 0xfef4, 0xfeef));
# endregion
#region ArabicYe ي
CharacterMap.Add(new PersianCharacter("ArabicYe", false,
0x64a, 0x64a, 0xfef2, 0xfef3, 0xfef4, 0xfef1));
# endregion
#region YeBaHamze ئ
CharacterMap.Add(new PersianCharacter("YeBaHamze", false,
0x626, 0x626, 0xfe8a, 0xfe8b, 0xfe8c, 0xfe89));
# endregion
}
/// <summary>
/// Check whether the character belongs to the Persian character list or not.
/// </summary>
/// <param name="ch"></param>
/// <returns>true if the character belongs to the
/// Persian character list; otherwise, false.</returns>
private bool IsPersianCharacter(char ch)
{
bool result = false;
var query = from cm in CharacterMap
where cm.StartChar == ch ||
cm.MiddleRightSideBoundedChar == ch ||
cm.MiddleLeftSideBoundedChar == ch ||
cm.MiddleTwoSideBoundedChar == ch ||
cm.EndingBoundedChar == ch ||
cm.EndingChar == ch
select cm.CharacterName;
if (query.Count() > 0)
{
result = true;
}
return result;
}
/// <summary>
/// Check whether the character is from NoLastAppend group or not.
/// </summary>
/// <param name="ch"></param>
/// <returns>true if the character is from NoLastAppend group;
/// otherwise, false.</returns>
private bool IsNoLastAppendCharacter(char ch)
{
bool result = false;
var query = from cm in CharacterMap
where (cm.StartChar == ch ||
cm.MiddleRightSideBoundedChar == ch ||
cm.MiddleLeftSideBoundedChar == ch ||
cm.MiddleTwoSideBoundedChar == ch ||
cm.EndingBoundedChar == ch ||
cm.EndingChar == ch) & cm.NoLastAppend == true
select cm.NoLastAppend;
if (query.Count() > 0)
{
result = true;
}
return result;
}
/// <summary>
/// Generates a correct Persian text to be presented
/// in the silverlight context.
/// </summary>
/// <param name="text"></param>
/// <returns>Persian correct format of the text</returns>
private string ToPersianString(string text)
{
int i = 0;
string str2 = "";
while (i < text.Length)
{
ECharPossition possition= ECharPossition.StartingChar;
// get current letter
if (IsPersianCharacter(Convert.ToChar(text.Substring(i, 1))))
{
if (i == 0)// This is the first chraracter of the string
{
possition = ECharPossition.StartingChar;
}
else if (i == (text.Length - 1))
// This is the last character of the string
{
// get letter before
if (IsPersianCharacter(Convert.ToChar(text.Substring(i - 1, 1))))
{
if (IsNoLastAppendCharacter(
Convert.ToChar(text.Substring(i - 1, 1))))
{
possition = ECharPossition.EndingChar;
}
else
{
possition = ECharPossition.EndingBoundedChar;
}
}
else
{
possition = ECharPossition.EndingBoundedChar;
}
}
else // the current character is neither first nor last
{
// get letter before
if (IsPersianCharacter(
Convert.ToChar(text.Substring(i - 1, 1))))
{
if (IsNoLastAppendCharacter(
Convert.ToChar(text.Substring(i - 1, 1))))
{
// get current letter
if (IsPersianCharacter(
Convert.ToChar(text.Substring(i, 1))))
{
if (!IsNoLastAppendCharacter(
Convert.ToChar(text.Substring(i, 1))))
{
possition =
ECharPossition.MiddleLeftSideBoundedChar;
}
else
{
possition = ECharPossition.StartingChar;
}
}
else
{
possition = ECharPossition.StartingChar;
}
}
else
{
possition = ECharPossition.MiddleTwoSidesBoundedChar;
}
}
else
{
possition = ECharPossition.StartingChar;
}
}
// get current letter
char currentChar = Convert.ToChar(text.Substring(i, 1));
var query = from cm in CharacterMap
where cm.StartChar == currentChar ||
cm.MiddleRightSideBoundedChar == currentChar ||
cm.MiddleLeftSideBoundedChar == currentChar ||
cm.MiddleTwoSideBoundedChar == currentChar ||
cm.EndingBoundedChar == currentChar ||
cm.EndingChar == currentChar
select cm;
//Retreive the character set of the current letter
PersianCharacter pch = query.First();
if (pch != null)
{
switch (possition)
{
case ECharPossition.StartingChar:
str2 = str2 +
Convert.ToChar(pch.MiddleTwoSideBoundedChar).ToString();
break;
case ECharPossition.MiddleRightSideBoundedChar: ;
str2 = str2 +
Convert.ToChar(pch.EndingBoundedChar).ToString();
break;
case ECharPossition.MiddleLeftSideBoundedChar:
str2 = str2 +
Convert.ToChar(pch.MiddleTwoSideBoundedChar).ToString();
break;
case ECharPossition.MiddleTwoSidesBoundedChar:
str2 = str2 +
Convert.ToChar(pch.EndingBoundedChar).ToString();
break;
case ECharPossition.EndingBoundedChar:
str2 = str2 +
Convert.ToChar(pch.MiddleLeftSideBoundedChar).ToString();
break;
case ECharPossition.EndingChar:
str2 = str2 + Convert.ToChar(pch.EndingChar).ToString();
break;
default:
break;
}
}
}
else
{
// The character does not belong to the CharMap
str2 = str2 + text.Substring(i, 1);
}
i++;
}
return this.ReverseString(str2);
}
public string ToPersian(string text)
{
string str = "";
string[] strArray0 = text.Split('\n');
for (int j = strArray0.Length - 1; j >= 0; j--)
{
string[] strArray1 = strArray0[j].Split(new char[] { ' ' });
int upperBound = strArray1.GetUpperBound(0);
for (int i = 0; i <= upperBound; i++)
{
str = this.ToPersianString(strArray1[i]) + " " + str;
}
str = "\n" + str;
}
str.Trim();
return str;
}
/// <summary>
/// Reverse the specified string to become right to left.
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private string ReverseString(string str)
{
string str2 = "";
for (int i = str.Length - 1; i >= 0; i--)
{
if (IsPersianCharacter(Convert.ToChar(str.Substring(i, 1))))
{
str2 = str2 + str.Substring(i, 1);
}
else
{
str2 = str.Substring(i, 1) + str2;
}
}
return str2;
}
private enum ECharPossition
{
StartingChar,
MiddleRightSideBoundedChar,
MiddleLeftSideBoundedChar,
MiddleTwoSidesBoundedChar,
EndingBoundedChar,
EndingChar
}
}
使用代码
此项目的源代码可在此处获得。