private void WriteCollationsElement(XElement collationsElem, Staging s) { var defaultCollationElem = new XElement("defaultCollation", "standard"); collationsElem.Add(defaultCollationElem); WriteCollationElement(collationsElem, s); }
private void WriteFontElement(XElement externalResourcesElem, Staging s) { var fontElem = new XElement(Sil + "font"); fontElem.SetAttributeValue("name", s.DefaultFontName); fontElem.SetOptionalAttributeValue("features", s.DefaultFontFeatures); externalResourcesElem.Add(fontElem); }
private void WriteTopLevelSpecialElements(XElement specialElem, Staging s) { XElement externalResourcesElem = specialElem.GetOrCreateElement(Sil + "external-resources"); if (!string.IsNullOrEmpty(s.DefaultFontName)) { WriteFontElement(externalResourcesElem, s); } }
/// <summary> /// Parse a character set from the Fw:validChars element and add it to the staging definition /// </summary> /// <param name="validCharsElem">XElement of Fw:validChars</param> /// <param name="s">staging definition where the character set definition will be added</param> /// <param name="elementName">name of the character set to read</param> /// <param name="type">character set definition type</param> private void AddCharacterSet(XElement validCharsElem, Staging s, string elementName, string type) { const char fwDelimiter = '\uFFFC'; const string spaceReplacement = "U+0020"; XElement elem = validCharsElem.Element(elementName); if ((elem != null) && !string.IsNullOrEmpty(type)) { var characterString = (string)elem; string[] characters = characterString.Replace(spaceReplacement, " ").Split(fwDelimiter); string characterSet = type != "numeric" ? UnicodeSet.ToPattern(characters) : string.Join("", characters); s.CharacterSets.Add(type, characterSet); } }
private void WriteCharactersElement(XElement charactersElem, Staging s) { // Convert each key value pair into character elements foreach (var kvp in s.CharacterSets.Where(kvp => kvp.Key != "numeric")) { // These character sets go to the normal LDML exemplarCharacters space // http://unicode.org/reports/tr35/tr35-general.html#Exemplars var exemplarCharactersElem = new XElement("exemplarCharacters", kvp.Value); // Assume main set doesn't have an attribute type if (kvp.Key != "main") { exemplarCharactersElem.SetAttributeValue("type", kvp.Key); } charactersElem.Add(exemplarCharactersElem); } }
private void WriteNumbersElement(XElement numbersElem, Staging s) { // Create defaultNumberingSystem element and add as the first child const string defaultNumberingSystem = "standard"; var defaultNumberingSystemElem = new XElement("defaultNumberingSystem", defaultNumberingSystem); numbersElem.AddFirst(defaultNumberingSystemElem); // Populate numbering system element var numberingSystemsElem = new XElement("numberingSystem"); numberingSystemsElem.SetAttributeValue("id", defaultNumberingSystem); numberingSystemsElem.SetAttributeValue("type", "numeric"); numberingSystemsElem.SetAttributeValue("digits", s.CharacterSets["numeric"]); numbersElem.Add(numberingSystemsElem); }
private void WriteIdentityElement(XElement identityElem, Staging s, string ietfLanguageTagAfterMigration) { WriteLanguageTagElements(identityElem, ietfLanguageTagAfterMigration); // Write generation date with UTC so no more ambiguity on timezone identityElem.SetAttributeValue("generation", "date", DateTime.UtcNow.ToISO8601TimeFormatWithUTCString()); // Create special element if data needs to be written if (!string.IsNullOrEmpty(s.WindowsLcid) || !string.IsNullOrEmpty(s.VariantName)) { XElement specialElem = CreateSpecialElement(identityElem); XElement silIdentityElem = specialElem.GetOrCreateElement(Sil + "identity"); silIdentityElem.SetOptionalAttributeValue("windowsLCID", s.WindowsLcid); silIdentityElem.SetOptionalAttributeValue("variantName", s.VariantName); } }
private void WriteCollationElement(XElement collationsElem, Staging s) { var collationElem = new XElement("collation", new XAttribute("type", "standard")); collationsElem.Add(collationElem); // Convert sort rules to collation definition of standard type switch (s.SortUsing) { case WritingSystemDefinitionV1.SortRulesType.CustomSimple: WriteCollationRulesFromCustomSimple(collationElem, s.SortRules); break; case WritingSystemDefinitionV1.SortRulesType.CustomICU: WriteCollationRulesFromCustomIcu(collationElem, s.SortRules); break; case WritingSystemDefinitionV1.SortRulesType.DefaultOrdering: break; } }
private static void ParseLegacyWordformingCharOverridesFile(Staging staging) { string legacyOverridesFile = GetLegacyWordformingCharOverridesPath(); if (File.Exists(legacyOverridesFile)) { XElement rootElem = XElement.Load(legacyOverridesFile); var characters = new HashSet <string>(); foreach (XElement charElem in rootElem.Elements("wordForming")) { var codepointStr = (string)charElem.Attribute("val"); if (!string.IsNullOrEmpty(codepointStr)) { int codepoint = Convert.ToInt32(codepointStr, 16); var c = (char)codepoint; characters.Add(c.ToString(CultureInfo.InvariantCulture)); } } if (characters.Count > 0) { staging.CharacterSets.Add("main", UnicodeSet.ToPattern(characters)); } } }
public override void Migrate(string sourceFilePath, string destinationFilePath) { string sourceFileName = Path.GetFileName(sourceFilePath); var writingSystemDefinitionV1 = new WritingSystemDefinitionV1(); new LdmlAdaptorV1().Read(sourceFilePath, writingSystemDefinitionV1); string abbreviation = writingSystemDefinitionV1.Abbreviation; float defaultFontSize = writingSystemDefinitionV1.DefaultFontSize; string keyboard = writingSystemDefinitionV1.Keyboard; string spellCheckingId = writingSystemDefinitionV1.SpellCheckingId; string defaultFontName = writingSystemDefinitionV1.DefaultFontName; string languageName = writingSystemDefinitionV1.LanguageName.IsOneOf("Unknown Language", "Language Not Listed") ? string.Empty : writingSystemDefinitionV1.LanguageName; string variant, privateUse; IetfLanguageTag.SplitVariantAndPrivateUse(writingSystemDefinitionV1.Variant, out variant, out privateUse); var langTagCleaner = new IetfLanguageTagCleaner(writingSystemDefinitionV1.Language, writingSystemDefinitionV1.Script, writingSystemDefinitionV1.Region, variant, privateUse); langTagCleaner.Clean(); string langTag = IetfLanguageTag.Canonicalize(langTagCleaner.GetCompleteTag()); List<string> knownKeyboards = writingSystemDefinitionV1.KnownKeyboards.Select(k => string.IsNullOrEmpty(k.Locale) ? k.Layout : string.Format("{0}_{1}", k.Locale, k.Layout)).ToList(); bool isGraphiteEnabled = false; string legacyMapping = string.Empty; string scriptName = string.Empty; string regionName = string.Empty; string variantName = string.Empty; SystemCollationDefinition scd = null; // Create system collation definition if applicable if ((writingSystemDefinitionV1.SortUsing == WritingSystemDefinitionV1.SortRulesType.OtherLanguage) && (!string.IsNullOrEmpty(writingSystemDefinitionV1.SortRules))) scd = new SystemCollationDefinition { LanguageTag = writingSystemDefinitionV1.SortRules }; // Migrate fields from legacy fw namespace, and then remove fw namespace XElement ldmlElem = XElement.Load(sourceFilePath); XElement fwElem = ldmlElem.Elements("special").FirstOrDefault(e => !string.IsNullOrEmpty((string) e.Attribute(XNamespace.Xmlns + "fw"))); if (fwElem != null) { XElement graphiteEnabledElem = fwElem.Element(FW + "graphiteEnabled"); if (graphiteEnabledElem != null) { if (!bool.TryParse((string) graphiteEnabledElem.Attribute("value"), out isGraphiteEnabled)) isGraphiteEnabled = false; } // LegacyMapping XElement legacyMappingElem = fwElem.Element(FW + "legacyMapping"); if (legacyMappingElem != null) legacyMapping = (string) legacyMappingElem.Attribute("value"); // ScriptName XElement scriptNameElem = fwElem.Element(FW + "scriptName"); if (scriptNameElem != null) scriptName = (string) scriptNameElem.Attribute("value"); // RegionName XElement regionNameElem = fwElem.Element(FW + "regionName"); if (regionNameElem != null) regionName = (string) regionNameElem.Attribute("value"); // VariantName XElement variantNameElem = fwElem.Element(FW + "variantName"); if (variantNameElem != null) variantName = (string) variantNameElem.Attribute("value"); } // Record the details for use in PostMigrate where we change the file name to match the ieft language tag where we can. var migrationInfo = new LdmlMigrationInfo(sourceFileName) { LanguageTagBeforeMigration = writingSystemDefinitionV1.Bcp47Tag, LanguageTagAfterMigration = langTag, RemovedPropertiesSetter = ws => { if (!string.IsNullOrEmpty(abbreviation)) ws.Abbreviation = abbreviation; if (defaultFontSize != 0) ws.DefaultFontSize = defaultFontSize; if (!string.IsNullOrEmpty(keyboard)) ws.Keyboard = keyboard; if (!string.IsNullOrEmpty(spellCheckingId)) ws.SpellCheckingId = spellCheckingId; if (!string.IsNullOrEmpty(defaultFontName)) ws.DefaultFont = ws.Fonts[defaultFontName]; if (!string.IsNullOrEmpty(languageName)) ws.Language = new LanguageSubtag(ws.Language, languageName); ws.IsGraphiteEnabled = isGraphiteEnabled; if (!string.IsNullOrEmpty(legacyMapping)) ws.LegacyMapping = legacyMapping; if (!string.IsNullOrEmpty(scriptName) && ws.Script != null && ws.Script.IsPrivateUse) ws.Script = new ScriptSubtag(ws.Script, scriptName); if (!string.IsNullOrEmpty(regionName) && ws.Region != null && ws.Region.IsPrivateUse) ws.Region = new RegionSubtag(ws.Region, regionName); if (scd != null) ws.DefaultCollation = scd; foreach (string keyboardId in knownKeyboards) { IKeyboardDefinition kd; if (!Keyboard.Controller.TryGetKeyboard(keyboardId, out kd)) kd = Keyboard.Controller.CreateKeyboard(keyboardId, KeyboardFormat.Unknown, Enumerable.Empty<string>()); ws.KnownKeyboards.Add(kd); } } }; _migrationInfo.Add(migrationInfo); // Store things that stay in ldml but are being moved: WindowsLcid, variantName, font, known keyboards, collations, font features, character sets // misc properties var staging = new Staging { WindowsLcid = writingSystemDefinitionV1.WindowsLcid, DefaultFontName = writingSystemDefinitionV1.DefaultFontName, SortUsing = writingSystemDefinitionV1.SortUsing, SortRules = writingSystemDefinitionV1.SortRules, }; // Determine if variantName is non-common private use before preserving it if (!string.IsNullOrEmpty(variantName)) { int index = IetfLanguageTag.GetIndexOfFirstNonCommonPrivateUseVariant(IetfLanguageTag.GetVariantSubtags(migrationInfo.LanguageTagAfterMigration)); if (index > -1) staging.VariantName = variantName; } if (fwElem != null) { // DefaultFontFeatures XElement fontFeatsElem = fwElem.Element(FW + "defaultFontFeatures"); if (fontFeatsElem != null && !string.IsNullOrEmpty(staging.DefaultFontName)) staging.DefaultFontFeatures = (string) fontFeatsElem.Attribute("value"); //MatchedPairs, PunctuationPatterns, QuotationMarks deprecated // Valid Chars XElement validCharsElem = fwElem.Element(FW + "validChars"); if (validCharsElem != null) { try { var fwValidCharsElem = XElement.Parse((string) validCharsElem.Attribute("value")); AddCharacterSet(fwValidCharsElem, staging, "WordForming", "main"); AddCharacterSet(fwValidCharsElem, staging, "Numeric", "numeric"); AddCharacterSet(fwValidCharsElem, staging, "Other", "punctuation"); } catch (XmlException) { ParseLegacyWordformingCharOverridesFile(staging); } } } _staging[sourceFileName] = staging; }
public override void Migrate(string sourceFilePath, string destinationFilePath) { string sourceFileName = Path.GetFileName(sourceFilePath); var writingSystemDefinitionV1 = new WritingSystemDefinitionV1(); new LdmlAdaptorV1().Read(sourceFilePath, writingSystemDefinitionV1); string abbreviation = writingSystemDefinitionV1.Abbreviation; float defaultFontSize = writingSystemDefinitionV1.DefaultFontSize; string keyboard = writingSystemDefinitionV1.Keyboard; string spellCheckingId = writingSystemDefinitionV1.SpellCheckingId; string defaultFontName = writingSystemDefinitionV1.DefaultFontName; string languageName = writingSystemDefinitionV1.LanguageName.IsOneOf("Unknown Language", "Language Not Listed") ? string.Empty : writingSystemDefinitionV1.LanguageName; string variant, privateUse; IetfLanguageTag.SplitVariantAndPrivateUse(writingSystemDefinitionV1.Variant, out variant, out privateUse); var langTagCleaner = new IetfLanguageTagCleaner(writingSystemDefinitionV1.Language, writingSystemDefinitionV1.Script, writingSystemDefinitionV1.Region, variant, privateUse); langTagCleaner.Clean(); string langTag = IetfLanguageTag.Canonicalize(langTagCleaner.GetCompleteTag()); List <string> knownKeyboards = writingSystemDefinitionV1.KnownKeyboards.Select(k => string.IsNullOrEmpty(k.Locale) ? k.Layout : string.Format("{0}_{1}", k.Locale, k.Layout)).ToList(); bool isGraphiteEnabled = false; string legacyMapping = string.Empty; string scriptName = string.Empty; string regionName = string.Empty; string variantName = string.Empty; SystemCollationDefinition scd = null; // Create system collation definition if applicable if ((writingSystemDefinitionV1.SortUsing == WritingSystemDefinitionV1.SortRulesType.OtherLanguage) && (!string.IsNullOrEmpty(writingSystemDefinitionV1.SortRules))) { scd = new SystemCollationDefinition { LanguageTag = writingSystemDefinitionV1.SortRules } } ; // Migrate fields from legacy fw namespace, and then remove fw namespace XElement ldmlElem = XElement.Load(sourceFilePath); XElement fwElem = ldmlElem.Elements("special").FirstOrDefault(e => !string.IsNullOrEmpty((string)e.Attribute(XNamespace.Xmlns + "fw"))); if (fwElem != null) { XElement graphiteEnabledElem = fwElem.Element(FW + "graphiteEnabled"); if (graphiteEnabledElem != null) { if (!bool.TryParse((string)graphiteEnabledElem.Attribute("value"), out isGraphiteEnabled)) { isGraphiteEnabled = false; } } // LegacyMapping XElement legacyMappingElem = fwElem.Element(FW + "legacyMapping"); if (legacyMappingElem != null) { legacyMapping = (string)legacyMappingElem.Attribute("value"); } // ScriptName XElement scriptNameElem = fwElem.Element(FW + "scriptName"); if (scriptNameElem != null) { scriptName = (string)scriptNameElem.Attribute("value"); } // RegionName XElement regionNameElem = fwElem.Element(FW + "regionName"); if (regionNameElem != null) { regionName = (string)regionNameElem.Attribute("value"); } // VariantName XElement variantNameElem = fwElem.Element(FW + "variantName"); if (variantNameElem != null) { variantName = (string)variantNameElem.Attribute("value"); } } // Record the details for use in PostMigrate where we change the file name to match the ieft language tag where we can. var migrationInfo = new LdmlMigrationInfo(sourceFileName) { LanguageTagBeforeMigration = writingSystemDefinitionV1.Bcp47Tag, LanguageTagAfterMigration = langTag, RemovedPropertiesSetter = ws => { if (!string.IsNullOrEmpty(abbreviation)) { ws.Abbreviation = abbreviation; } if (defaultFontSize != 0) { ws.DefaultFontSize = defaultFontSize; } if (!string.IsNullOrEmpty(keyboard)) { ws.Keyboard = keyboard; } if (!string.IsNullOrEmpty(spellCheckingId)) { ws.SpellCheckingId = spellCheckingId; } if (!string.IsNullOrEmpty(defaultFontName)) { ws.DefaultFont = ws.Fonts[defaultFontName]; } if (!string.IsNullOrEmpty(languageName)) { ws.Language = new LanguageSubtag(ws.Language, languageName); } ws.IsGraphiteEnabled = isGraphiteEnabled; if (!string.IsNullOrEmpty(legacyMapping)) { ws.LegacyMapping = legacyMapping; } if (!string.IsNullOrEmpty(scriptName) && ws.Script != null && ws.Script.IsPrivateUse) { ws.Script = new ScriptSubtag(ws.Script, scriptName); } if (!string.IsNullOrEmpty(regionName) && ws.Region != null && ws.Region.IsPrivateUse) { ws.Region = new RegionSubtag(ws.Region, regionName); } if (scd != null) { ws.DefaultCollation = scd; } foreach (string keyboardId in knownKeyboards) { IKeyboardDefinition kd; if (!Keyboard.Controller.TryGetKeyboard(keyboardId, out kd)) { kd = Keyboard.Controller.CreateKeyboard(keyboardId, KeyboardFormat.Unknown, Enumerable.Empty <string>()); } ws.KnownKeyboards.Add(kd); } } }; _migrationInfo.Add(migrationInfo); // Store things that stay in ldml but are being moved: WindowsLcid, variantName, font, known keyboards, collations, font features, character sets // misc properties var staging = new Staging { WindowsLcid = writingSystemDefinitionV1.WindowsLcid, DefaultFontName = writingSystemDefinitionV1.DefaultFontName, SortUsing = writingSystemDefinitionV1.SortUsing, SortRules = writingSystemDefinitionV1.SortRules, }; // Determine if variantName is non-common private use before preserving it if (!string.IsNullOrEmpty(variantName)) { int index = IetfLanguageTag.GetIndexOfFirstNonCommonPrivateUseVariant(IetfLanguageTag.GetVariantSubtags(migrationInfo.LanguageTagAfterMigration)); if (index > -1) { staging.VariantName = variantName; } } if (fwElem != null) { // DefaultFontFeatures XElement fontFeatsElem = fwElem.Element(FW + "defaultFontFeatures"); if (fontFeatsElem != null && !string.IsNullOrEmpty(staging.DefaultFontName)) { staging.DefaultFontFeatures = (string)fontFeatsElem.Attribute("value"); } //MatchedPairs, PunctuationPatterns, QuotationMarks deprecated // Valid Chars XElement validCharsElem = fwElem.Element(FW + "validChars"); if (validCharsElem != null) { try { var fwValidCharsElem = XElement.Parse((string)validCharsElem.Attribute("value")); AddCharacterSet(fwValidCharsElem, staging, "WordForming", "main"); AddCharacterSet(fwValidCharsElem, staging, "Numeric", "numeric"); AddCharacterSet(fwValidCharsElem, staging, "Other", "punctuation"); } catch (XmlException) { ParseLegacyWordformingCharOverridesFile(staging); } } } _staging[sourceFileName] = staging; }
private void WriteCharactersElement(XElement charactersElem, Staging s) { // Convert each key value pair into character elements foreach (var kvp in s.CharacterSets.Where(kvp => kvp.Key != "numeric")) { // These character sets go to the normal LDML exemplarCharacters space // http://unicode.org/reports/tr35/tr35-general.html#Exemplars var exemplarCharactersElem = new XElement("exemplarCharacters", kvp.Value); // Assume main set doesn't have an attribute type if (kvp.Key != "main") exemplarCharactersElem.SetAttributeValue("type", kvp.Key); charactersElem.Add(exemplarCharactersElem); } }
private void WriteTopLevelSpecialElements(XElement specialElem, Staging s) { XElement externalResourcesElem = specialElem.GetOrCreateElement(Sil + "external-resources"); if (!string.IsNullOrEmpty(s.DefaultFontName)) WriteFontElement(externalResourcesElem, s); }
/// <summary> /// Parse a character set from the Fw:validChars element and add it to the staging definition /// </summary> /// <param name="validCharsElem">XElement of Fw:validChars</param> /// <param name="s">staging definition where the character set definition will be added</param> /// <param name="elementName">name of the character set to read</param> /// <param name="type">character set definition type</param> private void AddCharacterSet(XElement validCharsElem, Staging s, string elementName, string type) { const char fwDelimiter = '\uFFFC'; const string spaceReplacement = "U+0020"; XElement elem = validCharsElem.Element(elementName); if ((elem != null) && !string.IsNullOrEmpty(type)) { var characterString = (string) elem; string[] characters = characterString.Replace(spaceReplacement, " ").Split(fwDelimiter); string characterSet = type != "numeric" ? UnicodeSet.ToPattern(characters) : string.Join("", characters); s.CharacterSets.Add(type, characterSet); } }
public override void PostMigrate(string sourcePath, string destinationPath) { EnsureIeftLanguageTagsUnique(_migrationInfo); // Write them back, with their new file name. foreach (LdmlMigrationInfo migrationInfo in _migrationInfo) { Staging staging = _staging[migrationInfo.FileName]; string sourceFilePath = Path.Combine(sourcePath, migrationInfo.FileName); string destinationFilePath = Path.Combine(destinationPath, migrationInfo.LanguageTagAfterMigration + ".ldml"); XElement ldmlElem = XElement.Load(sourceFilePath); // Remove legacy palaso namespace from sourceFilePath ldmlElem.Elements("special").Where(e => !string.IsNullOrEmpty((string)e.Attribute(XNamespace.Xmlns + "palaso"))).Remove(); ldmlElem.Elements("special").Where(e => !string.IsNullOrEmpty((string)e.Attribute(XNamespace.Xmlns + "palaso2"))).Remove(); ldmlElem.Elements("special").Where(e => !string.IsNullOrEmpty((string)e.Attribute(XNamespace.Xmlns + "fw"))).Remove(); // Remove collations to repopulate later ldmlElem.Elements("collations").Remove(); // Write out the elements. XElement identityElem = ldmlElem.Element("identity"); WriteIdentityElement(identityElem, staging, migrationInfo.LanguageTagAfterMigration); var layoutElement = ldmlElem.Element("layout"); WriteLayoutElement(layoutElement); if (staging.CharacterSets.ContainsKey("main") || staging.CharacterSets.ContainsKey("punctuation")) { XElement charactersElem = ldmlElem.GetOrCreateElement("characters"); WriteCharactersElement(charactersElem, staging); } if (staging.CharacterSets.ContainsKey("numeric")) { XElement numbersElem = ldmlElem.GetOrCreateElement("numbers"); WriteNumbersElement(numbersElem, staging); } if (staging.SortUsing != WritingSystemDefinitionV1.SortRulesType.OtherLanguage) { XElement collationsElem = ldmlElem.GetOrCreateElement("collations"); WriteCollationsElement(collationsElem, staging); } // If needed, create top level special for external resources if (!string.IsNullOrEmpty(staging.DefaultFontName)) { // Create special element XElement specialElem = CreateSpecialElement(ldmlElem); WriteTopLevelSpecialElements(specialElem, staging); } var writerSettings = CanonicalXmlSettings.CreateXmlWriterSettings(); writerSettings.NewLineOnAttributes = false; using (var writer = XmlWriter.Create(destinationFilePath, writerSettings)) ldmlElem.WriteTo(writer); if (migrationInfo.LanguageTagBeforeMigration != migrationInfo.LanguageTagAfterMigration) { _auditLog.LogChange(migrationInfo.LanguageTagBeforeMigration, migrationInfo.LanguageTagAfterMigration); } } if (_migrationHandler != null) { _migrationHandler(ToVersion, _migrationInfo); } }
private static void ParseLegacyWordformingCharOverridesFile(Staging staging) { string legacyOverridesFile = FileLocator.GetFileDistributedWithApplication(true, "WordFormingCharOverrides.xml"); if (!string.IsNullOrEmpty(legacyOverridesFile)) { XElement rootElem = XElement.Load(legacyOverridesFile); var characters = new HashSet<string>(); foreach (XElement charElem in rootElem.Elements("wordForming")) { var codepointStr = (string)charElem.Attribute("val"); if (!string.IsNullOrEmpty(codepointStr)) { int codepoint = Convert.ToInt32(codepointStr, 16); var c = (char)codepoint; characters.Add(c.ToString(CultureInfo.InvariantCulture)); } } if (characters.Count > 0) staging.CharacterSets.Add("main", UnicodeSet.ToPattern(characters)); } }