Beispiel #1
0
		/// <summary>
		/// Initializes a new instance of the <see cref="T:VariantSubtag"/> class.
		/// </summary>
		/// <param name="subtag">The subtag.</param>
		/// <param name="name">The name.</param>
		public VariantSubtag(VariantSubtag subtag, string name)
			: this(subtag.Code, name, subtag.IsPrivateUse, subtag._prefixes)
		{
		}
Beispiel #2
0
		/// <summary>
		/// Gets the subtags of the specified language tag.
		/// </summary>
		/// <param name="langTag">The language tag.</param>
		/// <param name="languageSubtag">The language subtag.</param>
		/// <param name="scriptSubtag">The script subtag.</param>
		/// <param name="regionSubtag">The region subtag.</param>
		/// <param name="variantSubtags">The variant and private-use subtags.</param>
		/// <returns></returns>
		public static bool TryGetSubtags(string langTag, out LanguageSubtag languageSubtag, out ScriptSubtag scriptSubtag,
			out RegionSubtag regionSubtag, out IEnumerable<VariantSubtag> variantSubtags)
		{
			if (langTag == null)
				throw new ArgumentNullException("langTag");

			languageSubtag = null;
			scriptSubtag = null;
			regionSubtag = null;
			variantSubtags = null;

			Match match = LangTagPattern.Match(langTag);
			if (!match.Success)
				return false;

			var privateUseCodes = new List<string>();
			Group privateUseGroup = match.Groups["privateuse"];
			if (privateUseGroup.Success)
				privateUseCodes.AddRange(privateUseGroup.Value.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries).Skip(1));

			Group languageGroup = match.Groups["language"];
			if (languageGroup.Success)
			{
				string languageCode = languageGroup.Value;
				if (languageCode.Equals(WellKnownSubtags.UnlistedLanguage, StringComparison.OrdinalIgnoreCase))
				{
					// In our own WS dialog, we don't allow no language, but if it isn't a standard one, a language like xkal
					// produces an identifier like qaa-x-kal, and we interepret the first thing after the x as a private
					// language code (not allowed as the first three characters according to the standard).
					// If it's NOT a valid language code (e.g., too many characters), probably came from some other
					// program. Treating it as a language code will fail if we try to create such a writing system,
					// since we will detect the invalid language code. So only interpret the first element
					// after the x as a language code if it is a valid one. Otherwise, we just let qaa be the language.
					if (privateUseCodes.Count > 0 && LangPattern.IsMatch(privateUseCodes[0])
						&& !StandardSubtags.CommonPrivateUseVariants.Contains(privateUseCodes[0]))
					{
						languageSubtag = new LanguageSubtag(privateUseCodes[0]);
						privateUseCodes.RemoveAt(0);
					}
					else
					{
						languageSubtag = WellKnownSubtags.UnlistedLanguage; // We do allow just plain qaa.
					}
				}
				else
				{
					if (!StandardSubtags.IsValidIso639LanguageCode(languageCode))
						return false;

					languageSubtag = languageCode;
				}
			}

			Group scriptGroup = match.Groups["script"];
			if (scriptGroup.Success)
			{
				string scriptCode = scriptGroup.Value;
				if (scriptCode.Equals("Qaaa", StringComparison.OrdinalIgnoreCase) && privateUseCodes.Count > 0
					&& ScriptPattern.IsMatch(privateUseCodes[0]))
				{

					scriptSubtag = new ScriptSubtag(privateUseCodes[0]);
					privateUseCodes.RemoveAt(0);
				}
				else
				{
					if (!StandardSubtags.IsValidIso15924ScriptCode(scriptCode))
						return false;

					scriptSubtag = scriptCode;
				}
			}

			Group regionGroup = match.Groups["region"];
			if (regionGroup.Success)
			{
				string regionCode = regionGroup.Value;
				if (regionCode.Equals("QM", StringComparison.OrdinalIgnoreCase) && privateUseCodes.Count > 0
					&& RegionPattern.IsMatch(privateUseCodes[0]))
				{
					regionSubtag = new RegionSubtag(privateUseCodes[0]);
					privateUseCodes.RemoveAt(0);
				}
				else
				{
					if (!StandardSubtags.IsValidIso3166RegionCode(regionCode))
						return false;

					regionSubtag = regionCode;
				}
			}

			if (scriptSubtag == null)
				scriptSubtag = GetImplicitScriptCode(languageSubtag, regionSubtag);

			var variants = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
			var variantSubtagsList = new List<VariantSubtag>();
			Group variantGroup = match.Groups["variant"];
			if (variantGroup.Success)
			{
				foreach (string variantCode in variantGroup.Value.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries))
				{
					if (variants.Contains(variantCode))
						return false;
					VariantSubtag variantSubtag;
					if (!StandardSubtags.RegisteredVariants.TryGet(variantCode, out variantSubtag))
						return false;
					variantSubtagsList.Add(variantSubtag);
					variants.Add(variantCode);
				}
			}

			variants.Clear();
			foreach (string privateUseCode in privateUseCodes)
			{
				if (variants.Contains(privateUseCode) || privateUseCode.Equals("x", StringComparison.InvariantCultureIgnoreCase))
					return false;
				VariantSubtag variantSubtag;
				if (!StandardSubtags.CommonPrivateUseVariants.TryGet(privateUseCode, out variantSubtag))
					variantSubtag = new VariantSubtag(privateUseCode);
				variantSubtagsList.Add(variantSubtag);
				variants.Add(privateUseCode);
			}
			variantSubtags = variantSubtagsList;
			return true;
		}
Beispiel #3
0
		/// <summary>
		/// This method will make the IetfLanguageTag unique compared to list of language tags passed in by
		/// appending dupl# where # is a digit that increases with the number of duplicates found.
		/// </summary>
		/// <param name="ietfLanguageTag"></param>
		/// <param name="otherLangTags"></param>
		public static string ToUniqueLanguageTag(string ietfLanguageTag, IEnumerable<string> otherLangTags)
		{
			// Parse for variants
			LanguageSubtag languageSubtag;
			ScriptSubtag scriptSubtag;
			RegionSubtag regionSubtag;
			IEnumerable<VariantSubtag> variantSubtags;
			if (!TryGetSubtags(ietfLanguageTag, out languageSubtag, out scriptSubtag, out regionSubtag, out variantSubtags))
				throw new ArgumentException("The IETF language tag is invalid.", "ietfLanguageTag");
			List<VariantSubtag> variants = variantSubtags.ToList();

			VariantSubtag lastDuplSubtag = null;
			int duplicateNumber = 0;
			var wsLangTags = new HashSet<string>(otherLangTags, StringComparer.InvariantCultureIgnoreCase);
			while (wsLangTags.Contains(ietfLanguageTag))
			{
				if (lastDuplSubtag != null)
					variants.Remove(lastDuplSubtag);
				var curDuplStubtag = new VariantSubtag(string.Format("dupl{0}", duplicateNumber));
				if (!variants.Contains(curDuplStubtag))
				{
					variants.Add(curDuplStubtag);
					lastDuplSubtag = curDuplStubtag;
				}
				duplicateNumber++;
				ietfLanguageTag = Create(languageSubtag, scriptSubtag, regionSubtag, variants);
			}
			return ietfLanguageTag;
		}
Beispiel #4
0
		public static bool TryGetVariantSubtags(string variantCodes, out IEnumerable<VariantSubtag> variantSubtags)
		{
			if (string.IsNullOrEmpty(variantCodes))
			{
				variantSubtags = Enumerable.Empty<VariantSubtag>();
				return true;
			}

			string standardVariantCodes, privateUseVariantCodes;
			SplitVariantAndPrivateUse(variantCodes, out standardVariantCodes, out privateUseVariantCodes);
			var variantSubtagsList = new List<VariantSubtag>();
			foreach (string standardCode in standardVariantCodes.Split(new[] {'-'}, StringSplitOptions.RemoveEmptyEntries))
			{
				VariantSubtag variantSubtag;
				if (StandardSubtags.RegisteredVariants.TryGet(standardCode, out variantSubtag))
				{
					variantSubtagsList.Add(variantSubtag);
				}
				else
				{
					variantSubtags = null;
					return false;
				}
			}

			foreach (string privateUseCode in privateUseVariantCodes.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries))
			{
				VariantSubtag variantSubtag;
				if (!StandardSubtags.CommonPrivateUseVariants.TryGet(privateUseCode, out variantSubtag))
					variantSubtag = new VariantSubtag(privateUseCode);
				variantSubtagsList.Add(variantSubtag);
			}
			variantSubtags = variantSubtagsList;
			return true;
		}
Beispiel #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="T:VariantSubtag"/> class.
 /// </summary>
 /// <param name="subtag">The subtag.</param>
 /// <param name="name">The name.</param>
 public VariantSubtag(VariantSubtag subtag, string name)
     : this(subtag.Code, name, subtag.IsPrivateUse, subtag.IsDeprecated, subtag._prefixes)
 {
 }