コード例 #1
0
        // There's some confusion between the Palaso migrator and our version 19 migrator about whether an old language
        // tag should have multiple X's if it has more than one private-use component. Since such X's are not
        // significant, ignore them.
        private bool TryGetNewTag(string oldTag, out string newTag)
        {
            string key = RemoveMultipleX(oldTag.ToLowerInvariant());

            if (m_tagMap.TryGetValue(key, out newTag))
            {
                return(!newTag.Equals(oldTag, StringComparison.OrdinalIgnoreCase));
            }
            var cleaner = new IetfLanguageTagCleaner(oldTag);

            cleaner.Clean();
            // FieldWorks needs to handle this special case.
            if (cleaner.Language.ToLowerInvariant() == "cmn")
            {
                var region = cleaner.Region;
                if (string.IsNullOrEmpty(region))
                {
                    region = "CN";
                }
                cleaner = new IetfLanguageTagCleaner("zh", cleaner.Script, region, cleaner.Variant, cleaner.PrivateUse);
            }
            newTag = cleaner.GetCompleteTag();
            while (m_tagMap.Values.Contains(newTag, StringComparer.OrdinalIgnoreCase))
            {
                // We can't use this tag because it would conflict with what we are mapping something else to.
                cleaner = new IetfLanguageTagCleaner(cleaner.Language, cleaner.Script, cleaner.Region, cleaner.Variant,
                                                     WritingSystemIdMigrator.GetNextDuplPart(cleaner.PrivateUse));
                newTag = cleaner.GetCompleteTag();
            }
            m_tagMap[key] = newTag;
            return(!newTag.Equals(oldTag, StringComparison.OrdinalIgnoreCase));
        }
コード例 #2
0
        public void CompleteTagConstructor_HasInvalidLanguageName_MovedToPrivateUse()
        {
            var cleaner = new IetfLanguageTagCleaner("234");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-x-234"));
        }
コード例 #3
0
        public void CompleteTagConstructor_XDashBeforeValidLanguageNameInVariant_NoChange()
        {
            var cleaner = new IetfLanguageTagCleaner("", "", "", "x-de", "");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("x-de"));
        }
コード例 #4
0
        public void Language_XDashBeforeString_AddsQaa()
        {
            var cleaner = new IetfLanguageTagCleaner("x-blah");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-x-blah"));
        }
コード例 #5
0
        public void CompleteTagConstructor_LanguageNameWithAudio_GetZxxxAdded()
        {
            var cleaner = new IetfLanguageTagCleaner("aaa-x-audio");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("aaa-Zxxx-x-audio"));
        }
コード例 #6
0
        private IEnumerable <Tuple <string, string> > GetLanguageAndKeyboardCombinations()
        {
            foreach (InputLanguage language in InputLanguage.InstalledInputLanguages)
            {
                CultureInfo culture;
                try
                {
                    //http://www.wesay.org/issues/browse/WS-34598
                    //Oddly enough, this can throw. It seems like it might have to do with a badly applied .Net patch
                    //http://www.ironspeed.com/Designer/3.2.4/WebHelp/Part_VI/Culture_ID__XXX__is_not_a_supported_culture.htm and others
                    culture = language.Culture;
                }
                catch (CultureNotFoundException)
                {
                    continue;
                }
                if (culture.EnglishName.StartsWith("Invariant"))
                {
                    continue;
                }
                string region = string.Empty;
                if (Environment.OSVersion.Platform != PlatformID.Unix)
                {
                    region = GetRegion(language);
                }

                var cleaner = new IetfLanguageTagCleaner(culture.TwoLetterISOLanguageName, "", region, "", "");
                cleaner.Clean();

                yield return(Tuple.Create(cleaner.GetCompleteTag(), language.LayoutName));
            }
        }
コード例 #7
0
        public void CompleteTagConstructor_HasLanguageNameAndOtherName_OtherNameMovedToPrivateUse()
        {
            var cleaner = new IetfLanguageTagCleaner("abc-123");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("abc-x-123"));
        }
コード例 #8
0
        public void CompleteTagConstructor_ValidRfctagWithLegacyIso3CodeAndPrivateUse_MigratesToRfc2LetterCodeAndPrivateUse()
        {
            var cleaner = new IetfLanguageTagCleaner("eng-bogus");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("en-x-bogus"));
        }
コード例 #9
0
        public void CompleteTagConstructor_TagContainsOnlyPrivateUseWithAdditionalXDash_RedundantXDashRemoved()
        {
            var cleaner = new IetfLanguageTagCleaner("x-some-x-whatever");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-x-some-whatever"));
        }
コード例 #10
0
        public void CompleteTagConstructor_PrivateUseWithAudioAndDuplicateX_MakesAudioTag()
        {
            var cleaner = new IetfLanguageTagCleaner("x-en-Zxxx-x-audio");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-Zxxx-x-en-Zxxx-audio"));
        }
コード例 #11
0
 void VerifyRfcCleaner(IetfLanguageTagCleaner cleaner, string language, string script, string region, string variant, string completeTag)
 {
     Assert.That(cleaner.Language, Is.EqualTo(language));
     Assert.That(cleaner.Script, Is.EqualTo(script));
     Assert.That(cleaner.Region, Is.EqualTo(region));
     Assert.That(cleaner.Variant, Is.EqualTo(variant));
     Assert.That(cleaner.GetCompleteTag(), Is.EqualTo(completeTag));
 }
コード例 #12
0
        public void CompleteTagConstructor_QaaWithXDashBeforeValidLanguageName_NoChange()
        {
            var cleaner = new IetfLanguageTagCleaner("qaa-x-th");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-x-th"));
            Assert.That(cleaner.Language, Is.EqualTo("qaa"));
            Assert.That(cleaner.PrivateUse, Is.EqualTo("th"));
        }
コード例 #13
0
        public void CompleteTagConstructor_ValidRfctagWithPrivateUseElements_NoChange()
        {
            var cleaner = new IetfLanguageTagCleaner("qaa-Zxxx-x-Zxxx-AUDIO");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-Zxxx-x-Zxxx-AUDIO"));
            // Except, it should have moved things from Language, where the constructor puts them, to the appropriate places.
            Assert.That(cleaner.Language, Is.EqualTo("qaa"));
            Assert.That(cleaner.Script, Is.EqualTo("Zxxx"));
            Assert.That(cleaner.PrivateUse, Is.EqualTo("Zxxx-AUDIO"));
        }
コード例 #14
0
        public void CompleteTagConstructor_InvalidLanguageNameWithScript_QaaAdded()
        {
            var cleaner = new IetfLanguageTagCleaner("wee-Latn");

            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-Latn-x-wee"));

            // Also when initially "Latn" is properly in the Script field.
            cleaner = new IetfLanguageTagCleaner("wee", "Latn", "", "", "");
            cleaner.Clean();
            Assert.That(cleaner.GetCompleteTag(), Is.EqualTo("qaa-Latn-x-wee"));
        }
コード例 #15
0
        ///<summary>
        /// Constructor.
        ///</summary>
        ///<param name="idsInFile"></param>
        ///<param name="replaceIdsInFile"></param>
        ///<param name="writingSystemRepository"></param>
        public static void FindOrphans(
            IEnumerable <string> idsInFile,
            IdReplacementStrategy replaceIdsInFile,
            IWritingSystemRepository writingSystemRepository)
        {
            List <string> originalIds = idsInFile.ToList();
            List <string> updatedIds  = originalIds.ToList();

            foreach (string wsId in originalIds)
            {
                // Check if it's in the repo
                if (writingSystemRepository.Contains(wsId))
                {
                    continue;
                }
                string newId;
                if (writingSystemRepository.WritingSystemIdHasChanged(wsId))
                {
                    newId = writingSystemRepository.WritingSystemIdHasChangedTo(wsId);
                }
                else
                {
                    // It's an orphan
                    // Clean it
                    var rfcTagCleaner = new IetfLanguageTagCleaner(wsId);
                    rfcTagCleaner.Clean();
                    newId = rfcTagCleaner.GetCompleteTag();
                }

                WritingSystemDefinition conformantWritingSystem;
                writingSystemRepository.WritingSystemFactory.Create(newId, out conformantWritingSystem);
                // If it changed, then change
                if (conformantWritingSystem.LanguageTag != wsId)
                {
                    conformantWritingSystem.LanguageTag = IetfLanguageTag.ToUniqueLanguageTag(
                        conformantWritingSystem.LanguageTag, updatedIds);
                    replaceIdsInFile(wsId, conformantWritingSystem.LanguageTag);
                    updatedIds.Remove(wsId);
                    updatedIds.Add(conformantWritingSystem.LanguageTag);
                }

                // Check if it's in the repo
                if (writingSystemRepository.Contains(conformantWritingSystem.LanguageTag))
                {
                    continue;
                }

                // It's not in the repo so set it
                writingSystemRepository.Set(conformantWritingSystem);
            }
            writingSystemRepository.Save();
        }
コード例 #16
0
        private bool TryGetNewLangTag(string oldTag, out string newTag)
        {
            if (m_tagMap.TryGetValue(oldTag, out newTag))
            {
                return(!newTag.Equals(oldTag));
            }

            var cleaner = new IetfLanguageTagCleaner(oldTag);

            cleaner.Clean();
            newTag = cleaner.GetCompleteTag();
            while (m_tagMap.Values.Contains(newTag))
            {
                // We can't use this tag because it would conflict with what we are mapping something else to.
                cleaner = new IetfLanguageTagCleaner(cleaner.Language, cleaner.Script, cleaner.Region, cleaner.Variant,
                                                     WritingSystemIdMigrator.GetNextDuplPart(cleaner.PrivateUse));
                newTag = cleaner.GetCompleteTag();
            }

            m_tagMap[oldTag] = newTag;
            return(!newTag.Equals(oldTag));
        }
コード例 #17
0
        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;
        }
コード例 #18
0
		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;
		}