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; }