X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=tools%2Flocale-builder%2FDriver.cs;h=52586043f241713ffeb53948ee225b67cc290485;hb=c0ba6dca416db15e7919fe775d29b9cf0124a611;hp=90d8e40a4d2f99b1ef2071308a21c60c3cd19831;hpb=7ff8f29ff29fa3f08ef305ac43ef079097323286;p=mono.git diff --git a/tools/locale-builder/Driver.cs b/tools/locale-builder/Driver.cs index 90d8e40a4d2..52586043f24 100644 --- a/tools/locale-builder/Driver.cs +++ b/tools/locale-builder/Driver.cs @@ -3,8 +3,9 @@ // // Author(s): // Jackson Harper (jackson@ximian.com) +// Atsushi Enomoto (atsushi@ximian.com) // -// (C) 2004 Novell, Inc (http://www.novell.com) +// (C) 2004-2005 Novell, Inc (http://www.novell.com) // @@ -46,7 +47,10 @@ namespace Mono.Tools.LocaleBuilder { private ArrayList cultures; private Hashtable langs; private Hashtable currency_types; - + private Hashtable regions; + + private XPathDocument lcids_doc; + // The lang is the language that display names will be displayed in public string Lang { get { @@ -73,35 +77,96 @@ namespace Mono.Tools.LocaleBuilder { public void Run () { + lcids_doc = GetXPathDocument ("lcids.xml"); + Regex locales_regex = null; if (Locales != null) locales_regex = new Regex (Locales); langs = new Hashtable (); cultures = new ArrayList (); + regions = new Hashtable (); + + LookupRegions (); LookupCurrencyTypes (); foreach (string file in Directory.GetFiles ("locales", "*.xml")) { string fn = Path.GetFileNameWithoutExtension (file); + if (fn == "hy_AM") + continue; // see bug #75499 if (locales_regex == null || locales_regex.IsMatch (fn)) { ParseLocale (fn); } } + /* FIXME: This is hacky. + * Since there is only langs/zh.xml while there are + * two "zh" languages (CHS and CHT), there should be + * different language profiles and we are not likely + * to add lang/* files. So here I just clone zh-CHS + * as zh-CHT + */ + foreach (CultureInfoEntry e in cultures) { + if (e.Name == "zh-CHS") { + CultureInfoEntry t = + CultureInfoEntry.ShallowCopy (e); + t.Language = "zh-CHT"; + LookupLcids (t, true); + cultures.Add (t); + break; + } + } + + ArrayList regionList = new ArrayList (regions.Values); + regionList.Sort (RegionComparer.Instance); + int number = 0; + foreach (RegionInfoEntry r in regionList) + r.RegionId = number++; + + foreach (CultureInfoEntry e in cultures) { + int lcid = int.Parse (e.Lcid.Substring (2), + NumberStyles.HexNumber); + int idx; + int start = e.Name.IndexOf ('-') + 1; + if (start == 0) + continue; + for (idx = start; idx < e.Name.Length; idx++) + if (!Char.IsLetter (e.Name [idx])) + break; + if (start == idx) { + Console.Error.WriteLine ("Culture {0} {1} is not mappable to Region.", e.Lcid, e.Name); + continue; + } + string name = e.Name.Substring (start, idx - start); + RegionInfoEntry rm = null; + foreach (RegionInfoEntry r in regions.Values) + if (r.ISO2Name == name) { + rm = r; + break; + } + if (rm == null) { + Console.Error.WriteLine ("No definition for region {0}", name); + continue; + } + e.RegionId = rm.RegionId; + } + /** * Dump each table individually. Using StringBuilders * because it is easier to debug, should switch to just * writing to streams eventually. */ using (StreamWriter writer = new StreamWriter (HeaderFileName, false, new UTF8Encoding (false, true))) { - + writer.NewLine = "\n"; writer.WriteLine (); + writer.WriteLine ("/* This is a generated file. Do not edit. See tools/locale-builder. */"); writer.WriteLine ("#ifndef MONO_METADATA_CULTURE_INFO_TABLES"); writer.WriteLine ("#define MONO_METADATA_CULTURE_INFO_TABLES 1"); writer.WriteLine ("\n"); writer.WriteLine ("#define NUM_CULTURE_ENTRIES " + cultures.Count); + writer.WriteLine ("#define NUM_REGION_ENTRIES " + regionList.Count); writer.WriteLine ("\n"); // Sort the cultures by lcid @@ -161,7 +226,7 @@ namespace Mono.Tools.LocaleBuilder { builder = new StringBuilder (); for (int i = 0; i < count; i++) { CultureInfoEntry ci = (CultureInfoEntry) cultures [i]; - builder.Append ("\t{\"" + ci.Name.ToLower () + "\", "); + builder.Append ("\t{" + Entry.EncodeStringIdx (ci.Name.ToLower ()) + ", "); builder.Append (ci.Row + "}"); if (i + 1 < count) builder.Append (','); @@ -172,20 +237,61 @@ namespace Mono.Tools.LocaleBuilder { writer.Write (builder); writer.WriteLine ("};\n\n"); + builder = new StringBuilder (); + int rcount = 0; + foreach (RegionInfoEntry r in regionList) { + r.AppendTableRow (builder); + if (++rcount != regionList.Count) + builder.Append (','); + builder.Append ('\n'); + } + writer.WriteLine ("static const RegionInfoEntry region_entries [] = {"); + writer.Write (builder); + writer.WriteLine ("};\n\n"); + + builder = new StringBuilder (); + rcount = 0; + foreach (RegionInfoEntry ri in regionList) { + builder.Append ("\t{" + Entry.EncodeStringIdx (ri.ISO2Name) + ", "); + builder.Append (ri.RegionId + "}"); + if (++rcount < regionList.Count) + builder.Append (','); + builder.Append ('\n'); + } + + writer.WriteLine ("static const RegionInfoNameEntry region_name_entries [] = {"); + writer.Write (builder); + writer.WriteLine ("};\n\n"); + + writer.WriteLine ("static const char locale_strings [] = {"); + writer.Write (Entry.GetStrings ()); + writer.WriteLine ("};\n\n"); + writer.WriteLine ("#endif\n"); } } private XPathDocument GetXPathDocument (string path) { - XmlTextReader xtr = new XmlTextReader (path); - xtr.XmlResolver = null; - return new XPathDocument (xtr); + XmlTextReader xtr = null; + try { + xtr = new XmlTextReader (path); + xtr.XmlResolver = null; + return new XPathDocument (xtr); + } finally { + if (xtr != null) + xtr.Close (); + } + } + + private string GetShortName (string lang) + { + return lang == "zh-CHS" ? "zh" : lang; } private bool ParseLang (string lang) { - XPathDocument doc = GetXPathDocument (Path.Combine ("langs", lang + ".xml")); + XPathDocument doc = GetXPathDocument (Path.Combine ("langs", GetShortName (lang) + ".xml")); XPathNavigator nav = doc.CreateNavigator (); CultureInfoEntry ci = new CultureInfoEntry (); string lang_type, terr_type; @@ -198,17 +304,17 @@ namespace Mono.Tools.LocaleBuilder { ci.Language = (lang_type == String.Empty ? null : lang_type); ci.Territory = (terr_type == String.Empty ? null : terr_type); - if (!LookupLcids (ci)) + if (!LookupLcids (ci, true)) return false; - doc = GetXPathDocument (Path.Combine ("langs", Lang + ".xml")); + doc = GetXPathDocument (Path.Combine ("langs", GetShortName (Lang) + ".xml")); nav = doc.CreateNavigator (); ci.DisplayName = LookupFullName (ci, nav); if (Lang == "en") { ci.EnglishName = ci.DisplayName; } else { - doc = GetXPathDocument (Path.Combine ("langs", Lang + ".xml")); + doc = GetXPathDocument (Path.Combine ("langs", GetShortName (lang) + ".xml")); nav = doc.CreateNavigator (); ci.EnglishName = LookupFullName (ci, nav); } @@ -216,7 +322,7 @@ namespace Mono.Tools.LocaleBuilder { if (ci.Language == Lang) { ci.NativeName = ci.DisplayName; } else { - doc = GetXPathDocument (Path.Combine ("langs", lang + ".xml")); + doc = GetXPathDocument (Path.Combine ("langs", GetShortName (lang) + ".xml")); nav = doc.CreateNavigator (); ci.NativeName = LookupFullName (ci, nav); } @@ -240,8 +346,8 @@ namespace Mono.Tools.LocaleBuilder { if (ci == null) return; - if (langs [ci.Language] == null) { - if (!ParseLang (ci.Language)) // If we can't parse the lang we cant have the locale + if (langs [GetLanguageFixed (ci)] == null) { + if (!ParseLang (GetLanguageFixed (ci))) // If we can't parse the lang we cant have the locale return; } @@ -250,7 +356,10 @@ namespace Mono.Tools.LocaleBuilder { private CultureInfoEntry LookupCulture (string locale) { - XPathDocument doc = GetXPathDocument (Path.Combine ("locales", locale + ".xml")); + string path = Path.Combine ("locales", locale + ".xml"); + if (!File.Exists (path)) + return null; + XPathDocument doc = GetXPathDocument (path); XPathNavigator nav = doc.CreateNavigator (); CultureInfoEntry ci = new CultureInfoEntry (); string supp; @@ -261,7 +370,7 @@ namespace Mono.Tools.LocaleBuilder { ci.Language = nav.Evaluate ("string (ldml/identity/language/@type)").ToString (); ci.Territory = nav.Evaluate ("string (ldml/identity/territory/@type)").ToString (); - if (!LookupLcids (ci)) + if (!LookupLcids (ci, false)) return null; LookupNames (ci); @@ -282,11 +391,11 @@ namespace Mono.Tools.LocaleBuilder { nav = doc.CreateNavigator (); Lookup (nav, ci); - doc = GetXPathDocument (Path.Combine ("langs", ci.Language + ".xml")); + doc = GetXPathDocument (Path.Combine ("langs", GetShortName (GetLanguageFixed (ci)) + ".xml")); nav = doc.CreateNavigator (); Lookup (nav, ci); - supp = Path.Combine ("supp", ci.Language + ".xml"); + supp = Path.Combine ("supp", GetLanguageFixed (ci) + ".xml"); if (File.Exists (supp)) { doc = GetXPathDocument (supp); nav = doc.CreateNavigator (); @@ -313,9 +422,22 @@ namespace Mono.Tools.LocaleBuilder { LookupNumberInfo (nav, ci); } + private string GetLanguageFixed (CultureInfoEntry ci) + { + // This is a hack, but without it nb-NO and nn-NO won't work. + if (ci.Territory == "NO") { + switch (ci.Language) { + case "nb": + case "nn": + return "no"; + } + } + return ci.Language; + } + private void LookupNames (CultureInfoEntry ci) { - XPathDocument doc = GetXPathDocument (Path.Combine ("langs", Lang + ".xml")); + XPathDocument doc = GetXPathDocument (Path.Combine ("langs", GetShortName (Lang) + ".xml")); XPathNavigator nav = doc.CreateNavigator (); ci.DisplayName = LookupFullName (ci, nav); @@ -331,12 +453,22 @@ namespace Mono.Tools.LocaleBuilder { if (ci.Language == Lang) { ci.NativeName = ci.DisplayName; } else { - doc = GetXPathDocument (Path.Combine ("langs", ci.Language + ".xml")); + // FIXME: We use ci.Language here. + // This is nothing more than hack for nb-NO and nn-NO + // where Parent of them is nn (not nb or nn). + string lang = ci.Language; + doc = GetXPathDocument (Path.Combine ("langs", GetShortName (lang) + ".xml")); nav = doc.CreateNavigator (); ci.NativeName = LookupFullName (ci, nav); } } + private void AddPattern (ArrayList al, string pattern) + { + if (!al.Contains (pattern)) + al.Add (pattern); + } + private void LookupDateTimeInfo (XPathNavigator nav, CultureInfoEntry ci) { /** @@ -391,6 +523,8 @@ namespace Mono.Tools.LocaleBuilder { df.MonthNames.Clear (); df.MonthNames.Add (ni2.Current.Value); } + if (df.MonthNames.Count == 12) + df.MonthNames.Add (String.Empty); ni2 = (XPathNodeIterator) ni.Current.Evaluate ("dayNames/day"); while (ni2.MoveNext ()) { @@ -412,6 +546,8 @@ namespace Mono.Tools.LocaleBuilder { df.AbbreviatedMonthNames.Clear (); df.AbbreviatedMonthNames.Add (ni2.Current.Value); } + if (df.AbbreviatedMonthNames.Count == 12) + df.AbbreviatedMonthNames.Add (String.Empty); ni2 = (XPathNodeIterator) ni.Current.Evaluate ("dateFormats/dateFormatLength"); while (ni2.MoveNext ()) { @@ -432,10 +568,13 @@ namespace Mono.Tools.LocaleBuilder { ext = df_nav.Select ("extraPatterns/pattern"); if (ext.MoveNext ()) { df.LongDatePatterns.Clear (); + AddPattern (df.LongDatePatterns, df.LongDatePattern); do { df.LongDatePatterns.Add (ext.Current.Value); } while (ext.MoveNext ()); } + else + AddPattern (df.LongDatePatterns, df.LongDatePattern); break; case "short": if (value != null) @@ -443,10 +582,13 @@ namespace Mono.Tools.LocaleBuilder { ext = df_nav.Select ("extraPatterns/pattern"); if (ext.MoveNext ()) { df.ShortDatePatterns.Clear (); + AddPattern (df.ShortDatePatterns, df.ShortDatePattern); do { df.ShortDatePatterns.Add (ext.Current.Value); } while (ext.MoveNext ()); } + else + AddPattern (df.ShortDatePatterns, df.ShortDatePattern); break; case "year_month": if (value != null) @@ -474,10 +616,13 @@ namespace Mono.Tools.LocaleBuilder { ext = df_nav.Select ("extraPatterns/pattern"); if (ext.MoveNext ()) { df.LongTimePatterns.Clear (); + AddPattern (df.LongTimePatterns, df.LongTimePattern); do { df.LongTimePatterns.Add (ext.Current.Value); } while (ext.MoveNext ()); } + else + AddPattern (df.LongTimePatterns, df.LongTimePattern); break; case "short": if (value != null) @@ -485,18 +630,21 @@ namespace Mono.Tools.LocaleBuilder { ext = df_nav.Select ("extraPatterns/pattern"); if (ext.MoveNext ()) { df.ShortTimePatterns.Clear (); + AddPattern (df.ShortTimePatterns, df.ShortTimePattern); do { df.ShortTimePatterns.Add (ext.Current.Value); } while (ext.MoveNext ()); } + else + AddPattern (df.ShortTimePatterns, df.ShortTimePattern); break; } } ni2 = (XPathNodeIterator) ni.Current.Evaluate ("dateTimeFormats/dateTimeFormatLength/dateTimeFormat/pattern"); if (ni2.MoveNext ()) - df.FullDateTimePattern = String.Format (ni2.Current.ToString (), - df.LongTimePattern, df.LongDatePattern); + df.RawFullDateTimePattern = ni2.Current.ToString ();/*String.Format (ni2.Current.ToString (), + df.LongTimePattern, df.LongDatePattern);*/ XPathNodeIterator am = ni.Current.SelectChildren ("am", ""); if (am.MoveNext ()) @@ -809,25 +957,29 @@ namespace Mono.Tools.LocaleBuilder { ci.NumberFormatEntry.CurrencySymbol = cur; } - private bool LookupLcids (CultureInfoEntry ci) + private bool LookupLcids (CultureInfoEntry ci, bool lang) { - XPathDocument doc = GetXPathDocument ("lcids.xml"); - XPathNavigator nav = doc.CreateNavigator (); - string name = ci.Language; + XPathNavigator nav = lcids_doc.CreateNavigator (); + string name = ci.Name; + // Language name does not always consist of locale name. + // (for zh-* it must be either zh-CHS or zh-CHT) + string langName = GetLanguageFixed (ci); - if (ci.Territory != null) - name += "-" + ci.Territory; +// if (ci.Territory != null) +// name += "-" + ci.Territory; XPathNodeIterator ni =(XPathNodeIterator) nav.Evaluate ("lcids/lcid[@name='" - + name + "']"); + + (lang ? langName : name) + "']"); if (!ni.MoveNext ()) { + Console.WriteLine ("no lcid found for: {0} ({1}/{2})", name, ci.Language, ci.Territory); string file; + if (ci.Territory != null) { file = Path.Combine ("locales", ci.Language + "_" + ci.Territory + ".xml"); - File.Delete (file); Console.WriteLine ("deleting file: " + file); + File.Delete (file); } - Console.WriteLine ("no lcid found for: " + name); + return false; } @@ -847,6 +999,8 @@ namespace Mono.Tools.LocaleBuilder { ci.ISO3Lang = iso3; ci.Win3Lang = win; ci.IcuName = icu; + + ci.TextInfoEntry = new TextInfoEntry (int.Parse (id.Substring (2), NumberStyles.HexNumber), GetXPathDocument ("textinfo.xml")); return true; } @@ -856,8 +1010,11 @@ namespace Mono.Tools.LocaleBuilder { string pre = "ldml/localeDisplayNames/"; string ret; + // FIXME: We use ci.Language here. + // This is nothing more than hack for nb-NO or nn-NO + // where Parent of them is nn (not nb or nn). ret = (string) nav.Evaluate ("string("+ - pre + "languages/language[@type='" + ci.Language + "'])"); + pre + "languages/language[@type='" + GetShortName (ci.Language) + "'])"); if (ci.Territory == null) return ret; @@ -867,6 +1024,42 @@ namespace Mono.Tools.LocaleBuilder { return ret; } + private void LookupRegions () + { + XPathDocument doc = GetXPathDocument ("supplementalData.xml"); + XPathNavigator nav = doc.CreateNavigator (); + XPathNodeIterator ni = nav.Select ("supplementalData/currencyData/region"); + while (ni.MoveNext ()) { + string territory = (string) ni.Current.GetAttribute ("iso3166", String.Empty); + string currency = (string) ni.Current.Evaluate ("string(currency/@iso4217)"); + RegionInfoEntry region = new RegionInfoEntry (); + region.ISO2Name = territory.ToUpper (); + region.ISOCurrencySymbol = currency; + regions [territory] = region; + } + + doc = GetXPathDocument ("langs/en.xml"); + nav = doc.CreateNavigator (); + ni = nav.Select ("/ldml/localeDisplayNames/territories/territory"); + while (ni.MoveNext ()) { + RegionInfoEntry r = (RegionInfoEntry) + regions [ni.Current.GetAttribute ("type", "")]; + if (r == null) + continue; + r.EnglishName = ni.Current.Value; + } + + Hashtable curNames = new Hashtable (); + ni = nav.Select ("/ldml/numbers/currencies/currency"); + while (ni.MoveNext ()) + curNames [ni.Current.GetAttribute ("type", "")] = + ni.Current.Evaluate ("string (displayName)"); + + foreach (RegionInfoEntry r in regions.Values) + r.CurrencyEnglishName = + (string) curNames [r.ISOCurrencySymbol]; + } + private void LookupCurrencyTypes () { XPathDocument doc = GetXPathDocument ("supplementalData.xml"); @@ -882,7 +1075,7 @@ namespace Mono.Tools.LocaleBuilder { } } - static string control_chars = "ghmsftz"; + static string control_chars = "eghmsftz"; // HACK: We are trying to build year_month and month_day patterns from the full pattern. private void ParseFullDateFormat (DateTimeFormatEntry df, string full) @@ -892,8 +1085,9 @@ namespace Mono.Tools.LocaleBuilder { string year_month = String.Empty; bool in_month_data = false; bool in_year_data = false; - int month_end = 0; - int year_end = 0; + int day_start = 0, day_end = 0; + int month_start = 0, month_end = 0; + int year_start = 0, year_end = 0; bool inquote = false; for (int i = 0; i < full.Length; i++) { @@ -903,18 +1097,24 @@ namespace Mono.Tools.LocaleBuilder { year_month += c; in_year_data = true; in_month_data = true; - month_end = month_day.Length; + if (month_start == 0) + month_start = i; + month_end = i; year_end = year_month.Length; } else if (!inquote && Char.ToLower (c) == 'd') { month_day += c; in_month_data = true; in_year_data = false; - month_end = month_day.Length; + if (day_start == 0) + day_start = i; + day_end = i; } else if (!inquote && Char.ToLower (c) == 'y') { year_month += c; in_year_data = true; in_month_data = false; - year_end = year_month.Length; + if (year_start == 0) + year_start = i; + year_end = i; } else if (!inquote && control_chars.IndexOf (Char.ToLower (c)) >= 0) { in_year_data = false; in_month_data = false; @@ -931,15 +1131,35 @@ namespace Mono.Tools.LocaleBuilder { } if (month_day != String.Empty) { - month_day = month_day.Substring (0, month_end); - df.MonthDayPattern = month_day; + //month_day = month_day.Substring (0, month_end); + df.MonthDayPattern = TrimPattern (month_day); } if (year_month != String.Empty) { - year_month = year_month.Substring (0, year_end); - df.YearMonthPattern = year_month; + //year_month = year_month.Substring (0, year_end); + df.YearMonthPattern = TrimPattern (year_month); } } + string TrimPattern (string p) + { + int idx = 0; + p = p.Trim ().TrimEnd (','); + idx = p.LastIndexOf ("' de '"); // spanish dates + if (idx > 0) + p = p.Substring (0, idx); + idx = p.LastIndexOf ("' ta '"); // finnish + if (idx > 0) + p = p.Substring (0, idx); + idx = p.LastIndexOf ("'ren'"); // euskara + if (idx > 0) + p = p.Replace ("'ren'", "").Trim (); + idx = p.LastIndexOf ("'a'"); // estonian + if (idx > 0) + p = p.Substring (0, idx); + + return p.Replace ("'ta '", "'ta'"); // finnish + } + private class LcidComparer : IComparer { public int Compare (object a, object b) @@ -958,9 +1178,34 @@ namespace Mono.Tools.LocaleBuilder { CultureInfoEntry aa = (CultureInfoEntry) a; CultureInfoEntry bb = (CultureInfoEntry) b; - return aa.Name.ToLower ().CompareTo (bb.Name.ToLower ()); + return String.CompareOrdinal(aa.Name.ToLower (), bb.Name.ToLower ()); } } + + class RegionComparer : IComparer + { + public static RegionComparer Instance = new RegionComparer (); + + public int Compare (object o1, object o2) + { + RegionInfoEntry r1 = (RegionInfoEntry) o1; + RegionInfoEntry r2 = (RegionInfoEntry) o2; + return String.CompareOrdinal ( + r1.ISO2Name, r2.ISO2Name); + } + } + + class RegionLCIDMap + { + public RegionLCIDMap (int lcid, int regionId) + { + LCID = lcid; + RegionId = regionId; + } + + public int LCID; + public int RegionId; + } } }