def load(self):
        """Load the glossary content into the database."""
        glossary_slugs = set()

        for filename in listdir(self.get_localised_dir(get_default_language())):
            if filename.endswith(self.FILE_EXTENSION):
                glossary_slug = filename[:-len(self.FILE_EXTENSION)]
                glossary_slugs.add(glossary_slug)

        for glossary_slug in sorted(glossary_slugs):
            term_translations = self.get_blank_translation_dictionary()

            content_filename = "{}.md".format(glossary_slug)
            content_translations = self.get_markdown_translations(content_filename)

            for language, content in content_translations.items():
                term_translations[language]["definition"] = content.html_string
                term_translations[language]["term"] = content.title

            glossary_term = GlossaryTerm(
                slug=glossary_slug,
            )
            self.populate_translations(glossary_term, term_translations)
            self.mark_translation_availability(glossary_term, required_fields=["term", "definition"])
            glossary_term.save()

            self.log("Added glossary term: {}".format(glossary_term.__str__()))

        self.log("{} glossary terms loaded!\n".format(len(glossary_slugs)))
Esempio n. 2
0
    def get_markdown_translations(self, filename, required=True, **kwargs):
        """Get dictionary of translations of the requested markdown file.

        Args:
            filename: (str) path to yaml file from the working directory of the loader
            required: (bool) raise an exception if the requested file is not present
                in the /en directory tree
            kwargs: (dict) kwargs passed through to convert_md_file

        Returns:
            dict mapping language codes to VertoResult objects

        Raises:
            CouldNotFindMarkdownFileError if the requested file could not be found
                in the /en directory tree
        """
        content_translations = {}
        for language in get_available_languages():
            try:
                content_translations[language] = self.convert_md_file(
                    self.get_localised_file(
                        language,
                        filename,
                    ), self.structure_file_path, **kwargs)
            except CouldNotFindMarkdownFileError:
                if required and language == get_default_language():
                    raise
        return content_translations
Esempio n. 3
0
    def get_activity_step_translations(self):
        """Get dictionary of translations of activity steps.

        Returns:
            Dictionary mapping language codes to VertoResult objects.

        Raises:
            CouldNotFindYAMLFileError: If the requested file could not be found
                in the /en directory tree
        """
        content_translations = {}
        for language in get_available_languages():
            try:
                content_translations[language] = self.convert_activity_step_file(
                    self.get_localised_file(
                        language,
                        ACTIVITY_STEPS_FILENAME,
                    )
                )
            except CouldNotFindYAMLFileError:
                if language == get_default_language():
                    raise
        return content_translations
Esempio n. 4
0
    def load(self):
        """Load the content for a section.

        Raises:
            MissingRequiredFieldError: When a config (yaml) file is missing a required
                field.
        """
        chapter_sections_structure = self.load_yaml_file(self.structure_file_path)
        section_numbers = []

        for (section_slug, section_structure) in chapter_sections_structure.items():

            if section_structure is None:
                raise MissingRequiredFieldError(
                    self.structure_file_path,
                    ["section-number"],
                    "ChapterSection"
                )

            section_number = section_structure.get("section-number", None)
            if section_number is None:
                raise MissingRequiredFieldError(
                    self.structure_file_path,
                    ["section-number"],
                    "ChapterSection"
                )
            if isinstance(section_number, int) is False:
                raise InvalidYAMLValueError(
                    self.structure_file_path,
                    "section-number - value '{}' is invalid".format(section_number),
                    "section-number must be an integer value."
                )

            section_numbers.append(section_number)

            chapter_section_translations = self.get_blank_translation_dictionary()

            content_filename = "{}.md".format(section_slug)
            content_translations = self.get_markdown_translations(content_filename)
            for language, content in content_translations.items():
                chapter_section_translations[language]["content"] = content.html_string
                chapter_section_translations[language]["name"] = content.title

            chapter_section = self.chapter.chapter_sections.create(
                slug=section_slug,
                number=section_number,
                languages=list(content_translations.keys()),
            )

            self.populate_translations(chapter_section, chapter_section_translations)
            self.mark_translation_availability(chapter_section, required_fields=["name", "content"])

            chapter_section.save()

            self.log("Added chapter section: {}".format(chapter_section.name), 1)

            check_interactives(
                content_translations[get_default_language()].required_files["interactives"],
                self.structure_file_path,
                self.chapter,
            )

            # Save chapter section headings
            self.factory.create_chapter_section_heading_loader(
                chapter_section,
                content_translations,
                base_path=self.base_path,
                structure_filename=self.structure_file_path,
            ).load()

        # assumes first section number is always 1
        for counter, section_number in enumerate(section_numbers, 1):
            if section_number != counter:
                raise InvalidYAMLValueError(
                    self.structure_file_path,
                    "section-number - value '{}' is invalid".format(section_number),
                    "section-numbers must be in sequential order. The next expected number was '{}'.".format(counter)
                )
Esempio n. 5
0
    def get_yaml_translations(self,
                              filename,
                              field_map=None,
                              required_slugs=[],
                              required_fields=[]):
        """Get a dictionary of translations for the given filename.

        Yaml files must be structured

            <object-slug-1>:
                <field-1>: <translated value for field-1>
                <field-2>: <translated value for field-2>
            <object-slug-2>
                ...

        where [object-slug-1, object-slug-2, ...] are slugs of objects of
        the same model (eg. ClassroomResource) and [field-1, field-2, ...]
        are the names of Char/TextFields defined on that model.

        Args:
            filename: (str) path to yaml file from the working directory of the loader
            field_map: (dict) optional mapping of field names in yaml file to
                field names in the resulting dictionary
            required_slugs: (list) list of slugs required to be present in the
                english strings file
            required_fields: (list) list of string fields required to be present
                for each model in the english strings file

        Returns:
            Dictonary of translations, structured as follows:
                {
                    <model-slug>: {
                        <language>: {
                            <field-name>:<value>
                        }
                    }
                }

        Raises:
            CouldNotFindYAMLFileError: the requested file could not be found in
                the /en directory, raised only if required_slugs is not empty.
            MissingRequiredModelsError: the file in the /en directory did not
                contain all slugs in required_slugs
            MissingRequiredFieldError: in the file in the /en directory, one
                of the models was missing an entry for a field in required_fields
            InvalidYAMLValueError: one of the 'translated strings' in the file
                was not a string.
        """
        translations = {}
        for language in get_available_languages():
            translations_filename = self.get_localised_file(language, filename)
            try:
                yaml = self.load_yaml_file(translations_filename)
            except CouldNotFindYAMLFileError:
                if required_slugs and language == get_default_language():
                    raise
                yaml = {}
            if language == get_default_language(
            ) and not set(required_slugs) <= set(yaml.keys()):
                raise MissingRequiredModelsError(
                    translations_filename,
                    set(required_slugs) - set(yaml.keys()),
                )

            for model_slug, model_fields in yaml.items():
                values_dict = {}
                for required_field in required_fields:
                    if language == get_default_language(
                    ) and required_field not in model_fields:
                        raise MissingRequiredFieldError(
                            translations_filename, [required_field],
                            "model ({})".format(model_slug))
                for field, value in model_fields.items():
                    if not isinstance(value, str):
                        raise InvalidYAMLValueError(
                            translations_filename,
                            "{}->{}".format(model_slug, field), "String")
                    if field_map:
                        field = field_map.get(field, field)
                    values_dict[field] = value
                translations.setdefault(model_slug,
                                        dict())[language] = values_dict
        return translations
    def load(self):
        """Load the content for a chapter.

        Raises:
            MissingRequiredFieldError: When a config (yaml) file is missing a required
                field.
        """
        chapter_structure = self.load_yaml_file(self.structure_file_path)

        sections = chapter_structure.get("sections", None)
        if sections is None:
            raise MissingRequiredFieldError(self.structure_file_path,
                                            ["sections"], "Chapter")

        chapter_translations = self.get_blank_translation_dictionary()

        introduction_filename = "{}.md".format(self.chapter_slug)
        introduction_translations = self.get_markdown_translations(
            introduction_filename)
        for language, content in introduction_translations.items():
            chapter_translations[language][
                "introduction"] = content.html_string
            chapter_translations[language]["name"] = content.title

        chapter_icon = chapter_structure.get("icon", None)
        if chapter_icon is None:
            raise MissingRequiredFieldError(self.structure_file_path, ["icon"],
                                            "Chapter")
        else:
            # TODO: Check icon exists here before path modification
            # Remove directory and extension as svg templatetag automatically adds these
            chapter_icon = chapter_icon[4:-4]

        video = chapter_structure.get("video", "")
        if video != "" and "vimeo" not in video:
            raise ValueError("Video must be a Vimeo video.")

        # Create chapter object and save to the db
        chapter = Chapter(slug=self.chapter_slug,
                          number=self.chapter_number,
                          icon=chapter_icon,
                          video=video)

        self.populate_translations(chapter, chapter_translations)
        self.mark_translation_availability(
            chapter, required_fields=["name", "introduction"])
        chapter.save()

        self.log("Added chapter: {}".format(chapter.name))

        check_interactives(
            introduction_translations[
                get_default_language()].required_files["interactives"],
            self.structure_file_path,
            chapter,
        )

        # Load chapter sections
        content_path, structure_filename = os.path.split(sections)
        self.factory.create_chapter_section_loader(
            chapter,
            base_path=self.base_path,
            content_path=os.path.join(self.content_path, content_path),
            structure_filename=structure_filename).load()