private Graph RenderGraph(LangFile langFile)
        {
            var graph = new Graph("OpenFoodFacts Category Taxonomy");

            var languageComparer = new LanguageByImportanceComparer(langFile.TranslationSets);
            var parentsComparer = new ParentsComparer(new AlphabeticalTranslationSetComparer(languageComparer, EvaluateMostImportantTranslation, GetLabel));

            foreach (var translationSet in langFile.TranslationSets.OrderBy(ts => ts.Parents, parentsComparer))
            {
                if (!translationSet.Translations.Any())
                {
                    continue;
                }

                var translation = EvaluateMostImportantTranslation(translationSet, languageComparer);
                var translationLabel = GetLabel(translation);

                if (translationSet.Parents.Any())
                {
                    foreach (var parent in translationSet.Parents)
                    {
                        var parentTranslation = EvaluateMostImportantTranslation(parent, languageComparer);
                        var parentTranslationLabel = GetLabel(parentTranslation);
                        graph.AddEdge(parentTranslationLabel, translationLabel);
                    }
                }
                else
                {
                    graph.AddNode(translationLabel);
                }
            }

            return graph;
        }
        private static void Validate(LangFile unlinkedFile)
        {
            var dupes = (from ts in unlinkedFile.TranslationSets
                         from t in ts.Translations
                         from w in t.Words
                         let word = new Word(w, t.Language)
                                    group word by word into g
                                    let cw = new WordCount(g.Key, g.Count())
                                             where cw.Count > 1
                                             orderby cw.Count descending
                                             select cw).ToList();

            if (dupes.Count > 0)
            {
                throw new DuplicateWordsException(dupes);
            }
        }
        private static IReadOnlyDictionary <Word, TranslationSet> GetReverseMap(LangFile unlinkedFile)
        {
            Validate(unlinkedFile);

            var result = new Dictionary <Word, TranslationSet>();

            foreach (var translationSet in unlinkedFile.TranslationSets)
            {
                foreach (var translation in translationSet.Translations)
                {
                    foreach (var word in translation.Words)
                    {
                        result.Add(new Word(word, translation.Language), translationSet);
                    }
                }
            }

            return(new WordTranslationSetDictionary(result));
        }
        private static IReadOnlyDictionary<Word, TranslationSet> GetReverseMap(LangFile unlinkedFile)
        {
            Validate(unlinkedFile);

            var result = new Dictionary<Word, TranslationSet>();

            foreach (var translationSet in unlinkedFile.TranslationSets)
            {
                foreach (var translation in translationSet.Translations)
                {
                    foreach (var word in translation.Words)
                    {
                        result.Add(new Word(word, translation.Language), translationSet);
                    }
                }
            }

            return new WordTranslationSetDictionary(result);
        }
        private static void Validate(LangFile unlinkedFile)
        {
            var dupes = (from ts in unlinkedFile.TranslationSets
                         from t in ts.Translations
                         from w in t.Words
                         let word = new Word(w, t.Language)
                         group word by word into g
                         let cw = new WordCount(g.Key, g.Count())
                         where cw.Count > 1
                         orderby cw.Count descending
                         select cw).ToList();

            if (dupes.Count > 0)
            {
                throw new DuplicateWordsException(dupes);
            }
        }