コード例 #1
0
 public void SubTagComponentDescription_HasForwardSlash_ReplacesWithPipe()
 {
     Assert.AreEqual(
         "=|Kx'au||'ein",
         StandardSubtags.SubTagComponentDescription("Description: =/Kx'au//'ein")
         );
 }
コード例 #2
0
 public void SubTagComponentDescription_HasIndividualLanguage_RemovesIt()
 {
     Assert.AreEqual(
         "Malay",
         StandardSubtags.SubTagComponentDescription("Description: Malay (individual language)")
         );
 }
コード例 #3
0
        public void ConvertToPalasoConformPrivateUseRfc5646Tag(string flexConformPrivateUseRfc5646Tag)
        {
            string language   = String.Empty;
            string script     = String.Empty;
            string region     = String.Empty;
            string variant    = String.Empty;
            string privateUse = String.Empty;

            var tokens = flexConformPrivateUseRfc5646Tag.Split(new[] { '-' });

            for (int position = 0; position < tokens.Length; ++position)
            {
                string currentToken = tokens[position];
                if (position == 0)
                {
                    if (!currentToken.Equals("x", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new ValidationException(String.Format("The rfctag {0} does not start with 'x-' or 'X-'.",
                                                                    flexConformPrivateUseRfc5646Tag));
                    }
                    language = currentToken;
                }
                else if (position == 1 && !StandardSubtags.IsValidIso15924ScriptCode(currentToken))
                {
                    language = language + '-' + currentToken;
                }
                else if (StandardSubtags.IsValidIso15924ScriptCode(currentToken))
                {
                    if (!String.IsNullOrEmpty(region) || !String.IsNullOrEmpty(variant))
                    {
                        throw new ValidationException(
                                  String.Format(
                                      "The rfctag '{0}' contains a misplaced Script subtag (i.e. it was preceded by a region or variant subtag.",
                                      flexConformPrivateUseRfc5646Tag));
                    }
                    script = currentToken;
                }
                else if (StandardSubtags.IsValidIso3166RegionCode(currentToken))
                {
                    if (!String.IsNullOrEmpty(variant))
                    {
                        throw new ValidationException(
                                  String.Format(
                                      "The rfctag '{0}' contains a misplaced Region subtag (i.e. it was preceded by a variant subtag.",
                                      flexConformPrivateUseRfc5646Tag));
                    }
                    region = currentToken;
                }
                else if (StandardSubtags.IsValidRegisteredVariantCode(currentToken))
                {
                    variant = variant + currentToken;
                }
                else
                {
                    privateUse = String.IsNullOrEmpty(privateUse) ? currentToken : privateUse + '-' + currentToken;
                }
            }
            variant = IetfLanguageTag.ConcatenateVariantAndPrivateUse(variant, privateUse);
            ConvertToPalasoConformPrivateUseRfc5646Tag(language, script, region, variant);
        }
コード例 #4
0
 public void SubTagComponentDescription_HasAliasFor_RemovesAliasFor()
 {
     Assert.AreEqual(
         "Japanese (Han + Hiragana + Katakana)",
         StandardSubtags.SubTagComponentDescription("Description: Japanese (alias for Han + Hiragana + Katakana)")
         );
 }
コード例 #5
0
 [TestCase("A1B2", false)]         // Valid script code that will is unlikely to be registered
 public void VerifyAddedPrivateUseScriptsMarkedProperly(string scriptCode, bool expectedValue)
 {
     StandardSubtags.RegisteredScripts.Remove(scriptCode);
     StandardSubtags.AddScript(scriptCode, "description");
     Assert.AreEqual(StandardSubtags.RegisteredScripts[scriptCode].IsPrivateUse, expectedValue);
     StandardSubtags.RegisteredScripts.Remove(scriptCode);
 }
コード例 #6
0
 public void SubTagComponentDescription_HasBeginningParenthesis_RemovesParens()
 {
     Assert.AreEqual(
         "Hiragana + Katakana",
         StandardSubtags.SubTagComponentDescription("Description: (Hiragana + Katakana)")
         );
 }
コード例 #7
0
        private void ValidateVariant()
        {
            var invalidPart = _variant.AllParts.FirstOrDefault(part => !StandardSubtags.IsValidRegisteredVariantCode(part));

            if (!String.IsNullOrEmpty(invalidPart))
            {
                throw new ValidationException(
                          String.Format("'{0}' is not a valid registered variant code.", invalidPart)
                          );
            }
            _variant.ThrowIfSubtagContainsDuplicates();
        }
コード例 #8
0
        ///<summary>Constructor method to parse a valid RFC5646 tag as a string
        ///</summary>
        ///<param name="inputString">valid RFC5646 string</param>
        ///<returns>RFC5646Tag object</returns>
        public static Rfc5646Tag Parse(string inputString)
        {
            var tokens = inputString.Split(new[] { '-' });

            var rfc5646Tag = new Rfc5646Tag();

            bool haveX = false;

            for (int position = 0; position < tokens.Length; ++position)
            {
                var token = tokens[position];
                if (token == "x")
                {
                    haveX = true;
                    continue;
                }
                if (haveX)
                {
                    //This is the case for RfcTags consisting only of a private use subtag
                    if (position == 1)
                    {
                        rfc5646Tag = new Rfc5646Tag(String.Empty, String.Empty, String.Empty, String.Empty, token);
                        continue;
                    }
                    rfc5646Tag.AddToPrivateUse(token);
                    continue;
                }
                if (position == 0)
                {
                    rfc5646Tag.Language = token;
                    continue;
                }
                if (position <= 1 && StandardSubtags.IsValidIso15924ScriptCode(token))
                {
                    rfc5646Tag.Script = token;
                    continue;
                }
                if (position <= 2 && StandardSubtags.IsValidIso3166RegionCode(token))
                {
                    rfc5646Tag.Region = token;
                    continue;
                }
                if (StandardSubtags.IsValidRegisteredVariantCode(token))
                {
                    rfc5646Tag.AddToVariant(token);
                    continue;
                }
                throw new ValidationException(String.Format("The RFC tag '{0}' could not be parsed.", inputString));
            }
            return(rfc5646Tag);
        }
コード例 #9
0
        public async Task <Attempt <ParatextUserInfo> > TryGetUserInfoAsync(User user)
        {
            if ((await TryCallApiAsync(_dataAccessClient, user, HttpMethod.Get, "projects"))
                .TryResult(out string response))
            {
                var repos   = XElement.Parse(response);
                var repoIds = new HashSet <string>(repos.Elements("repo").Select(r => (string)r.Element("projid")));
                if ((await TryCallApiAsync(_registryClient, user, HttpMethod.Get, "projects"))
                    .TryResult(out response))
                {
                    var projectArray = JArray.Parse(response);
                    var projects     = new List <ParatextProject>();
                    foreach (JToken projectObj in projectArray)
                    {
                        JToken identificationObj = projectObj["identification_systemId"]
                                                   .FirstOrDefault(id => (string)id["type"] == "paratext");
                        if (identificationObj == null)
                        {
                            continue;
                        }
                        string projectId = (string)identificationObj["text"];
                        if (!repoIds.Contains(projectId))
                        {
                            continue;
                        }

                        var langName = (string)projectObj["language_iso"];
                        if (StandardSubtags.TryGetLanguageFromIso3Code(langName, out LanguageSubtag subtag))
                        {
                            langName = subtag.Name;
                        }

                        projects.Add(new ParatextProject
                        {
                            Id           = projectId,
                            Name         = (string)identificationObj["fullname"],
                            LanguageTag  = (string)projectObj["language_ldml"],
                            LanguageName = langName
                        });
                    }
                    return(Attempt.Success(new ParatextUserInfo
                    {
                        Username = GetUsername(user),
                        Projects = projects
                    }));
                }
            }
            return(Attempt <ParatextUserInfo> .Failure);
        }
コード例 #10
0
 private void ValidateRegion()
 {
     if (String.IsNullOrEmpty(_region))
     {
         return;
     }
     if (_region.Contains("-"))
     {
         throw new ValidationException("The region tag may not contain dashes or underscores. I.e. there may only be a single iso 639 tag in this subtag");
     }
     if (!StandardSubtags.IsValidIso3166RegionCode(_region))
     {
         throw new ValidationException(String.Format("'{0}' is not a valid ISO-3166 region code.", _region));
     }
 }
コード例 #11
0
 private void ValidateScript()
 {
     if (String.IsNullOrEmpty(_script))
     {
         return;
     }
     if (_script.Contains("-"))
     {
         throw new ValidationException("The script tag may not contain dashes or underscores. I.e. there may only be a single iso 639 tag in this subtag");
     }
     if (!StandardSubtags.IsValidIso15924ScriptCode(_script))
     {
         throw new ValidationException(String.Format("'{0}' is not a valid ISO-15924 script code.", _script));
     }
 }
コード例 #12
0
        private void ValidateLanguage()
        {
            if (String.IsNullOrEmpty(_language))
            {
                return;
            }

            if (_language.Contains("-"))
            {
                throw new ValidationException(
                          "The language tag may not contain dashes. I.e. there may only be a single iso 639 tag in this subtag"
                          );
            }
            if (!StandardSubtags.IsValidIso639LanguageCode(_language))
            {
                throw new ValidationException(String.Format("'{0}' is not a valid ISO-639 language code.", _language));
            }
        }
コード例 #13
0
ファイル: Extensions.cs プロジェクト: vkarthim/libpalaso
        public static string ToValidVariantString(this string unknownString)
        {
            // var1-var2-var3
            // var1-privateUse1-x-privateUse2
            unknownString = unknownString.Trim();
            unknownString = Regex.Replace(unknownString, @"[ ,.]", "-");
            unknownString = Regex.Replace(unknownString, @"-+", "-");
            var  tokens     = unknownString.Split('-');
            var  variants   = new List <string>();
            var  privateUse = new List <string>();
            bool haveSeenX  = false;

            foreach (string token in tokens)
            {
                if (token == "x")
                {
                    haveSeenX = true;
                    continue;
                }
                if (!haveSeenX && StandardSubtags.IsValidRegisteredVariantCode(token))
                {
                    variants.Add(token);
                }
                else
                {
                    privateUse.Add(token);
                }
            }
            string combinedVariant    = String.Join("-", variants.ToArray());
            string combinedPrivateUse = String.Join("-", privateUse.ToArray());
            string variantString      = combinedVariant;

            if (!String.IsNullOrEmpty(combinedPrivateUse))
            {
                variantString = "x-" + combinedPrivateUse;
                if (!String.IsNullOrEmpty(combinedVariant))
                {
                    variantString = combinedVariant + "-" + variantString;
                }
            }
            return(variantString);
        }
コード例 #14
0
        /// <summary>
        /// A smarter way to get a name for an iso code. Recent rework on writing systems in libpalaso has
        /// apparently fixed much of our problems as StandardSubtags.TryGetLanguageFromIso3Code() finds 3-letter
        /// entries now. This adds fall-backs for 2-letter codes and strips off Script/Region/Variant codes.
        /// If we can't find ANY name, the out param is set to the isoCode itself, and we return false.
        /// </summary>
        /// <returns>true if it found a name</returns>
        public static bool GetBestLanguageName(this LanguageLookupModel isoModel, string isoCode, out string name)
        {
            // BL-8081/8096: Perhaps we got in here with Script/Region/Variant tag(s).
            // Try to get a match on the part of the isoCode up to the first hyphen.
            var codeToMatch = GetGeneralCode(isoCode.ToLowerInvariant());

            if (!string.IsNullOrEmpty(codeToMatch))
            {
                LanguageSubtag match;
                if (StandardSubtags.TryGetLanguageFromIso3Code(codeToMatch, out match))
                {
                    name = match.Name;
                    return(true);
                }
                // Perhaps we only have a 2-letter code (e.g. 'fr'), in that case, this will likely find it.
                if (StandardSubtags.RegisteredLanguages.TryGet(codeToMatch, out match))
                {
                    name = match.Name;
                    return(true);
                }
            }
            name = isoCode;             // At this point, the best name we can come up with is the isoCode itself.
            return(false);
        }
コード例 #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LanguageDataIndex"/> class.
        /// </summary>
        public LanguageDataIndex(IDictionary <string, string> sourcefiles)
        {
            string twotothreecodes = sourcefiles["TwoToThreeCodes.txt"];
            string subtagregistry  = sourcefiles["ianaSubtagRegistry.txt"];

            StandardSubtags.InitialiseIanaSubtags(twotothreecodes, subtagregistry);

            // First read in Ethnologue data file into temporary dictionary
            var threeToTwoLetter = StandardSubtags.TwoAndThreeMap(twotothreecodes, true);

            //LanguageIndex.txt Format: LangID	CountryID	NameType	Name
            //a language appears on one row for each of its alternative langauges
            string languageindex = sourcefiles["LanguageIndex.txt"];
            var    entries       = new List <string>(languageindex.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries));

            entries.Add("qaa\t?\tL\tUnlisted Language");

            foreach (string entry in entries.Skip(1))             //skip the header
            {
                string[] items = entry.Split('\t');
                if (items.Length != 4)
                {
                    continue;
                }
                if (items[2].StartsWith("!"))                 //temporary suppression of entries while waiting for Ethnologue changes
                {
                    continue;
                }
                // excluded by !
                // all gax (ET,KE,SO) including L
                // all gaz (ET) including L
                // all hae (ET) including L

                string code = items[0].Trim();
                string twoLetterCode;
                string threelettercode = code;
                if (threeToTwoLetter.TryGetValue(code, out twoLetterCode))
                {
                    code = twoLetterCode;
                }

                //temporary suppression of entries while waiting for Ethnologue changes (those excluded by !)
                if (ExcludedCodes.Contains(code))
                {
                    continue;
                }

                string       regionCode = items[1].Trim();
                LanguageInfo language   = GetOrCreateLanguageFromCode(code, threelettercode, regionCode == "?" ? "" : StandardSubtags.RegisteredRegions[regionCode].Name);

                string name = items[3].Trim();


                if (items[2].Trim() == "L")
                {
                    while (language.Names.Contains(name))
                    {
                        language.Names.Remove(name);
                    }
                    language.Names.Insert(0, name);
                }
                else
                {
                    if (items[2].Contains("P"))
                    {
                        //Skip pejorative
                    }
                    else if (ExcludedRegions.Contains(StandardSubtags.RegisteredRegions[regionCode].Name))
                    {
                        //Skip alternatives for Ethiopia, as per request
                    }
                    else if (code == "gax" || code == "om")
                    {
                        //For these two "Oromo" languages, skip all related languages as per request
                    }
                    else if (!language.Names.Contains(name))
                    {
                        language.Names.Add(name);                         //intentionally not lower-casing
                    }
                }
            }

            // Then for each registered ietf language tag create a real entry and add the ethnologue data to it
            IOrderedEnumerable <LanguageSubtag> languages = StandardSubtags.RegisteredLanguages.OrderBy(lang => lang.Iso3Code);

            foreach (LanguageSubtag language in languages)
            {
                bool singlename = false;
                if (language.IsDeprecated || ExcludedCodes.Contains(language.Code))
                {
                    continue;
                }
                LanguageInfo langinfo = GetOrCreateLanguageFromCode(language.Code, language.Iso3Code, null);
                langinfo.DesiredName     = language.Name.Replace("'", "’");
                langinfo.IsMacroLanguage = language.IsMacroLanguage;

                foreach (string country in langinfo.Countries)
                {
                    if (ExcludedRegions.Contains(country))
                    {
                        singlename = true;
                    }
                }

                foreach (string name in language.Names)
                {
                    string langname = name.Replace("'", "’");
                    if (!langinfo.Names.Contains(langname))
                    {
                        if (singlename && langinfo.Names.Count == 1)
                        {
                            // leave single ethnologue names
                            break;
                        }
                        else
                        {
                            langinfo.Names.Add(langname);
                        }
                    }
                    if (singlename)
                    {
                        break;
                    }
                }
                _codeToLanguageIndex.Add(language.Code, langinfo);
            }

            IEnumerable <IGrouping <string, string> > languageGroups = Sldr.LanguageTags.Where(info => info.IsAvailable && IetfLanguageTag.IsValid(info.LanguageTag))
                                                                       .Select(info => IetfLanguageTag.Canonicalize(info.LanguageTag))
                                                                       .GroupBy(IetfLanguageTag.GetLanguagePart);

            foreach (IGrouping <string, string> languageGroup in languageGroups)
            {
                string[] langTags = languageGroup.ToArray();
                if (langTags.Length == 1)
                {
                    string       langTag = langTags[0];
                    LanguageInfo language;
                    if (langTag != languageGroup.Key && _codeToLanguageIndex.TryGetValue(languageGroup.Key, out language))
                    {
                        _codeToLanguageIndex.Remove(languageGroup.Key);
                        language.LanguageTag          = langTag;
                        _codeToLanguageIndex[langTag] = language;
                    }
                }
                else
                {
                    foreach (string langTag in langTags)
                    {
                        LanguageSubtag languageSubtag;
                        ScriptSubtag   scriptSubtag;
                        RegionSubtag   regionSubtag;
                        IEnumerable <VariantSubtag> variantSubtags;
                        if (IetfLanguageTag.TryGetSubtags(langTag, out languageSubtag, out scriptSubtag, out regionSubtag, out variantSubtags))
                        {
                            if (langTag == languageSubtag)
                            {
                                continue;
                            }

                            LanguageInfo language      = GetOrCreateLanguageFromCode(langTag, langTag, regionSubtag == null ? "" : regionSubtag.Name);                        // changed to default to "" 2017-04-24
                            bool         displayScript = scriptSubtag != null && !IetfLanguageTag.IsScriptImplied(langTag);
                            LanguageInfo otherLanguage;
                            if (langTag != languageSubtag && !displayScript && _codeToLanguageIndex.TryGetValue(languageSubtag, out otherLanguage) && language.Countries.SetEquals(otherLanguage.Countries))
                            {
                                language.Names.AddRange(otherLanguage.Names);
                            }
                            else
                            {
                                string name = displayScript ? string.Format("{0} ({1})", languageSubtag.Name, scriptSubtag.Name) : languageSubtag.Name;
                                if (!language.Names.Contains(name))
                                {
                                    language.Names.Add(name);                                     //intentionally not lower-casing
                                }
                            }
                            LanguageInfo keylanguage;
                            if (_codeToLanguageIndex.TryGetValue(languageGroup.Key, out keylanguage))
                            {
                                language.IsMacroLanguage = keylanguage.IsMacroLanguage;
                            }
                            _codeToLanguageIndex.Add(langTag, language);
                        }
                    }
                }
            }

            string languagecodes = sourcefiles["LanguageCodes.txt"];
            var    codeentries   = new List <string>(languagecodes.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries));

            foreach (var languageCode in codeentries)
            {
                var data = languageCode.Split(new[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
                if (data.Length < 2)
                {
                    continue;
                }
                var    langCode = data[0];
                string twoLetterCode;
                if (threeToTwoLetter.TryGetValue(langCode, out twoLetterCode))
                {
                    langCode = twoLetterCode;
                }
                if (langCode == "fuv")
                {
                    langCode = "fuv-Arab";                      // special case because the script has been added to this language code
                }
                // which is probably something to do with the SLDR
                var          countryCode = data[1];
                LanguageInfo lang;
                if (_codeToLanguageIndex.TryGetValue(langCode, out lang))
                {
                    lang.PrimaryCountry = StandardSubtags.RegisteredRegions[countryCode].Name;
                }
            }

            // localise some language names
            foreach (LanguageInfo languageInfo in _codeToLanguageIndex.Values)
            {
                if (languageInfo.Names.Count == 0)
                {
                    continue;                     // this language is suppressed
                }
                //Why just this small set? Only out of convenience. Ideally we'd have a db of all languages as they write it in their literature.
                string localName = null;
                switch (languageInfo.Names[0])
                {
                case "French":
                    localName = "français";
                    break;

                case "Spanish":
                    localName = "español";
                    break;

                case "Chinese":
                    localName = "中文";
                    break;

                case "Hindi":
                    localName = "हिन्दी";
                    break;

                case "Bengali":
                    localName = "বাংলা";
                    break;

                case "Telugu":
                    localName = "తెలుగు";
                    break;

                case "Tamil":
                    localName = "தமிழ்";
                    break;

                case "Urdu":
                    localName = "اُردُو";
                    break;

                case "Arabic":
                    localName = "العربية/عربي";
                    break;

                case "Thai":
                    localName = "ภาษาไทย";
                    break;

                case "Indonesian":
                    localName = "Bahasa Indonesia";
                    break;
                }
                if (!string.IsNullOrEmpty(localName))
                {
                    if (languageInfo.Names.Contains(localName))
                    {
                        languageInfo.Names.Remove(localName);
                    }
                    languageInfo.Names.Insert(0, localName);
                    languageInfo.DesiredName = localName;
                }

                switch (languageInfo.ThreeLetterTag)
                {
                case "itd":                         // 2 temporary special cases because the LanguageCodes.txt files needs to be updated with LanguageIndex.txt
                    languageInfo.PrimaryCountry = "Indonesia";
                    break;

                case "xak":
                    languageInfo.PrimaryCountry = "Venezuela";
                    break;

                default:
                    // Also set the PrimaryCountry if there is only one country
                    if (String.IsNullOrEmpty(languageInfo.PrimaryCountry) && languageInfo.Countries.Count == 1)
                    {
                        languageInfo.PrimaryCountry = languageInfo.Countries.First();
                    }
                    break;
                }
            }

            // check if any languages are found in multiple countries but do not have a primary country
            // there is a test for this in LanguageLookupTests.llExpectedLanguagesHaveUniquePrimaryCountries
            var languagesWithoutRegions = new List <LanguageInfo>();

            foreach (var lang in _codeToLanguageIndex.Values)
            {
                if (String.IsNullOrEmpty(lang.PrimaryCountry))
                {
                    languagesWithoutRegions.Add(lang);
                }
            }
            var languagesWithAmbiguousPrimaryCountry = languagesWithoutRegions.Where(l => l.Countries.Count() > 1);

            foreach (var lang in languagesWithAmbiguousPrimaryCountry)
            {
                Console.WriteLine("Language {0}({1}) has no primary country but is found in multiple countries", lang.DesiredName, lang.LanguageTag);
            }
        }
コード例 #16
0
 public void IsValidIso15924ScriptCode_Qaaa_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsValidIso15924ScriptCode("Qaaa"), Is.True);
 }
コード例 #17
0
 public void IsValidIso639LanguageCode_qaa_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsValidIso639LanguageCode("qaa"), Is.True);
 }
コード例 #18
0
 public void IsValidIso639LanguageCode_fonipa_ReturnFalse()
 {
     Assert.That(StandardSubtags.IsValidIso639LanguageCode("fonipa"), Is.False);
 }
コード例 #19
0
 public void IsValidRegisteredVariant_fonipa_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsValidRegisteredVariantCode("fonipa"), Is.True);
 }
コード例 #20
0
 public void IsValidRegisteredVariant_en_ReturnsFalse()
 {
     Assert.That(StandardSubtags.IsValidRegisteredVariantCode("en"), Is.False);
 }
コード例 #21
0
 public void IsValidIso3166Region_fonipa_ReturnsFalse()
 {
     Assert.That(StandardSubtags.IsValidIso3166RegionCode("fonipa"), Is.False);
 }
コード例 #22
0
 public void IsPrivateUseRegionCode_QM_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsPrivateUseRegionCode("QM"), Is.True);
 }
コード例 #23
0
 public void IsValidIso3166Region_QM_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsValidIso3166RegionCode("QM"), Is.True);
     Assert.That(StandardSubtags.IsValidIso3166RegionCode("qm"), Is.True);
 }
コード例 #24
0
 public void IsValidIso3166Region_US_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsValidIso3166RegionCode("US"), Is.True);
 }
コード例 #25
0
 public void IsValidIso639LanguageCode_two_ReturnTrue()
 {
     // Yes it's true
     Assert.That(StandardSubtags.IsValidIso639LanguageCode("two"), Is.True);
 }
コード例 #26
0
 public void IsPrivateUseScriptCode_Qaaa_ReturnsTrue()
 {
     Assert.That(StandardSubtags.IsPrivateUseScriptCode("Qaaa"), Is.True);
 }
コード例 #27
0
 public void IsValidIso15924ScriptCode_fonipa_ReturnsFalse()
 {
     Assert.That(StandardSubtags.IsValidIso15924ScriptCode("fonipa"), Is.False);
 }
コード例 #28
0
        /// <summary>
        /// Cleans the tag.
        /// </summary>
        public void Clean()
        {
            // Migrate legacy ISO3 language codes to IANA 2 letter language codes, if there's a match.
            // Do this before we look for valid codes, otherwise the 3-letter ones come up as invalid and
            // get moved to private use. However, only do this to languages not identified as private-use.
            if (!Language.StartsWith("x-", StringComparison.OrdinalIgnoreCase))
            {
                string migrateFrom = "";
                string migrateTo   = "";
                foreach (string part in _languageSubTag.AllParts)
                {
                    if (part.Equals("x", StringComparison.OrdinalIgnoreCase))
                    {
                        break;                         // don't migrate language code parts already explicitly marked private-use.
                    }
                    if (string.IsNullOrEmpty(migrateFrom))
                    {
                        LanguageSubtag language;
                        if (StandardSubtags.TryGetLanguageFromIso3Code(part, out language) && language.Code != language.Iso3Code)
                        {
                            migrateFrom = part;
                            migrateTo   = language.Code;
                        }
                    }
                }
                if (!String.IsNullOrEmpty(migrateFrom))
                {
                    _languageSubTag.RemoveParts(migrateFrom);
                    _languageSubTag.AddToSubtag(migrateTo);
                }
            }
            // The very next thing, before anything else gets moved to private use, is to move the parts whose position we
            // care about to the appropriate position in the private use section.
            // In the process we may remove anything non-alphanumeric, since otherwise we may move a marker that later
            // disappears (pathologically).
            MoveFirstPartToPrivateUseIfNecessary(_languageSubTag, StandardSubtags.IsValidIso639LanguageCode, "qaa", true);
            MoveFirstPartToPrivateUseIfNecessary(_scriptSubTag, StandardSubtags.IsValidIso15924ScriptCode, "Qaaa", false);
            MoveFirstPartToPrivateUseIfNecessary(_regionSubTag, StandardSubtags.IsValidIso3166RegionCode, "QM", false);
            //This fixes a bug where the LdmlAdaptorV1 was writing out Zxxx as part of the variant to mark an audio writing system
            if (_variantSubTag.Contains(WellKnownSubtags.AudioScript))
            {
                MoveTagsMatching(_variantSubTag, _scriptSubTag, tag => tag.Equals(WellKnownSubtags.AudioScript));
                _privateUseSubTag.AddToSubtag(WellKnownSubtags.AudioPrivateUse);
            }
            // Fixes various legacy problems.
            if (Language.Equals("cmn", StringComparison.OrdinalIgnoreCase))
            {
                Language = "zh";
            }
            if (Language.Equals("pes", StringComparison.OrdinalIgnoreCase))
            {
                Language = "fa";
            }
            if (Language.Equals("arb", StringComparison.OrdinalIgnoreCase))
            {
                Language = "ar";
            }
            if (Language.Equals("zh", StringComparison.OrdinalIgnoreCase) && String.IsNullOrEmpty(Region))
            {
                Region = "CN";
            }

            // If the language tag contains an x- , then move the string behind the x- to private use
            MovePartsToPrivateUseIfNecessary(_languageSubTag);

            // Move script, region, and variant present in the langauge tag to their proper subtag.
            MoveTagsMatching(_languageSubTag, _scriptSubTag, StandardSubtags.IsValidIso15924ScriptCode, StandardSubtags.IsValidIso639LanguageCode);
            MoveTagsMatching(_languageSubTag, _regionSubTag, StandardSubtags.IsValidIso3166RegionCode, StandardSubtags.IsValidIso639LanguageCode);
            MoveTagsMatching(_languageSubTag, _variantSubTag, StandardSubtags.IsValidRegisteredVariantCode, StandardSubtags.IsValidIso639LanguageCode);

            // Move all other tags that don't belong to the private use subtag.

            //keep track of everything that we moved
            var tempSubTag = new SubTag();

            MoveTagsMatching(_languageSubTag, tempSubTag, tag => !StandardSubtags.IsValidIso639LanguageCode(tag));
            //place all the moved parts in private use.
            foreach (var part in tempSubTag.AllParts)
            {
                _privateUseSubTag.AddToSubtag(part);
                //if it looks like we moved a custom script set the subtag to mark that we've moved it
                if (_scriptSubTag.IsEmpty &&
                    part.Length == 4 &&                     //potential custom script tag
                    !WellKnownSubtags.IpaPhonemicPrivateUse.EndsWith(part) &&
                    !WellKnownSubtags.IpaPhoneticPrivateUse.EndsWith(part))
                {
                    _scriptSubTag = new SubTag("Qaaa");
                }
            }

            MoveTagsMatching(_scriptSubTag, _privateUseSubTag, tag => !StandardSubtags.IsValidIso15924ScriptCode(tag));
            MoveTagsMatching(_regionSubTag, _privateUseSubTag, tag => !StandardSubtags.IsValidIso3166RegionCode(tag));
            MoveTagsMatching(_variantSubTag, _privateUseSubTag, tag => !StandardSubtags.IsValidRegisteredVariantCode(tag));

            _languageSubTag.KeepFirstAndMoveRemainderTo(_privateUseSubTag);
            _scriptSubTag.KeepFirstAndMoveRemainderTo(_privateUseSubTag);
            _regionSubTag.KeepFirstAndMoveRemainderTo(_privateUseSubTag);

            if (_privateUseSubTag.Contains(WellKnownSubtags.AudioPrivateUse))
            {
                // Move every tag that's not a Zxxx to private use
                if (!_scriptSubTag.IsEmpty && !_scriptSubTag.Contains(WellKnownSubtags.AudioScript))
                {
                    MoveTagsMatching(_scriptSubTag, _privateUseSubTag, tag => !_privateUseSubTag.Contains(tag));
                }
                // If we don't have a Zxxx already, set it. This protects tags already present, but with unusual case
                if (!_scriptSubTag.Contains(WellKnownSubtags.AudioScript))
                {
                    _scriptSubTag = new SubTag(WellKnownSubtags.AudioScript);
                }
            }

            //These two methods may produce duplicates that will subsequently be removed. Do we care? - TA 29/3/2011
            _privateUseSubTag.RemoveNonAlphaNumericCharacters();
            _privateUseSubTag.TruncatePartsToNumCharacters(8);

            _variantSubTag.RemoveDuplicates();
            _privateUseSubTag.RemoveDuplicates();
            // Any 'x' in the other tags will have arrived in the privateUse tag, so remove them.
            _privateUseSubTag.RemoveParts("x");

            // if language is empty, we need to add qaa, unless only a privateUse is present (e.g. x-blah is a valid rfc5646 tag)
            if ((_languageSubTag.IsEmpty && (!_scriptSubTag.IsEmpty || !_regionSubTag.IsEmpty || !_variantSubTag.IsEmpty)) ||
                (_languageSubTag.IsEmpty && _scriptSubTag.IsEmpty && _regionSubTag.IsEmpty && _variantSubTag.IsEmpty && _privateUseSubTag.IsEmpty))
            {
                _languageSubTag.AddToSubtag("qaa");
            }

            // Two more legacy problems. We don't allow -etic or -emic without fonipa, so insert if needed.
            // If it has some other standard variant we won't be able to fix it...not sure what the right answer would be.
            // At least we catch the more common case.
            foreach (string part in _privateUseSubTag.AllParts)
            {
                if (string.IsNullOrEmpty(Variant) &&
                    (part.Equals("etic", StringComparison.OrdinalIgnoreCase) || part.Equals("emic", StringComparison.OrdinalIgnoreCase)))
                {
                    Variant = "fonipa";
                }
            }
        }
コード例 #29
0
        public async Task <IReadOnlyList <ParatextProject> > GetProjectsAsync(UserEntity user)
        {
            var    accessToken   = new JwtSecurityToken(user.ParatextTokens.AccessToken);
            Claim  usernameClaim = accessToken.Claims.FirstOrDefault(c => c.Type == "username");
            string username      = usernameClaim?.Value;
            string response      = await CallApiAsync(_dataAccessClient, user, HttpMethod.Get, "projects");

            var reposElem = XElement.Parse(response);
            var repos     = new Dictionary <string, string>();

            foreach (XElement repoElem in reposElem.Elements("repo"))
            {
                var      projId   = (string)repoElem.Element("projid");
                XElement userElem = repoElem.Element("users")?.Elements("user")
                                    ?.FirstOrDefault(ue => (string)ue.Element("name") == username);
                repos[projId] = (string)userElem?.Element("role");
            }
            Dictionary <string, SFProjectEntity> existingProjects = (await _projects.Query()
                                                                     .Where(p => repos.Keys.Contains(p.ParatextId))
                                                                     .ToListAsync())
                                                                    .ToDictionary(p => p.ParatextId);

            response = await CallApiAsync(_registryClient, user, HttpMethod.Get, "projects");

            var projectArray = JArray.Parse(response);
            var projects     = new List <ParatextProject>();

            foreach (JToken projectObj in projectArray)
            {
                JToken identificationObj = projectObj["identification_systemId"]
                                           .FirstOrDefault(id => (string)id["type"] == "paratext");
                if (identificationObj == null)
                {
                    continue;
                }
                string paratextId = (string)identificationObj["text"];
                if (!repos.TryGetValue(paratextId, out string role))
                {
                    continue;
                }

                // determine if the project is connectable, i.e. either the project exists and the user hasn't been
                // added to the project, or the project doesn't exist and the user is the administrator
                bool   isConnectable;
                bool   isConnected = false;
                string projectId   = null;
                if (existingProjects.TryGetValue(paratextId, out SFProjectEntity project))
                {
                    projectId     = project.Id;
                    isConnected   = true;
                    isConnectable = !project.Users.Any(u => u.UserRef == user.Id);
                }
                else if (role == SFProjectRoles.Administrator)
                {
                    isConnectable = true;
                }
                else
                {
                    isConnectable = false;
                }

                var langName = (string)projectObj["language_iso"];
                if (StandardSubtags.TryGetLanguageFromIso3Code(langName, out LanguageSubtag subtag))
                {
                    langName = subtag.Name;
                }

                projects.Add(new ParatextProject
                {
                    ParatextId    = paratextId,
                    Name          = (string)identificationObj["fullname"],
                    LanguageTag   = (string)projectObj["language_ldml"],
                    LanguageName  = langName,
                    ProjectId     = projectId,
                    IsConnectable = isConnectable,
                    IsConnected   = isConnected
                });
            }
            return(projects);
        }