Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translations: add jinja and js translations #78

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .tx/config
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,36 @@ file_filter = invenio_pages/translations/<lang>/LC_MESSAGES/messages.po
source_file = invenio_pages/translations/messages.pot
source_lang = en
type = PO

# Translate JavaScript strings
# 1) Navigate to the invenio_administration/assets/semantic-ui/translations/invenio_administration folder
# 2) Install i18n dev dependencies
# npm install
# 3) Add a new language
# npm run init_catalog lang <lang>
# 4) Extract translation keys/values
# $ npm run extract_messages
# 5) Update the ./messages/index.js file
# import TRANSLATE_<lang> from './<lang>/translations.json'
# export const translations = {
# ...rest,
# <lang>: { translation: TRANSLATE_<lang> }
# }
# 6) Install the transifex-client
# $ pip install transifex-client
# 7) Push source (.pot) and translations (.po) to Transifex
# $ tx push -s -t
# 8) Pull translations for a single language from Transifex
# $ tx pull -l <lang>
# 9) Pull translations for all languages from Transifex
# $ tx pull -a
# 10) Compile .po files for all languages
# $ npm run compile_catalog
# 11) Convert .po file for a single language
# $ npm run compile_catalog lang <lang>

[invenio.invenio-pages-messages-ui]
file_filter = invenio_pages/assets/semantic-ui/translations/invenio_pages/messages/<lang>/messages.po
source_file = invenio_pages/assets/semantic-ui/translations/invenio_pages/translations.pot
source_lang = en
type = PO
10 changes: 1 addition & 9 deletions babel.ini
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2015-2022 CERN.
# Copyright (C) 2015-2023 CERN.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

# Extraction from Python source files

[python: **.py]
encoding = utf-8

# Extraction from Jinja2 templates

[jinja2: **/templates/**.html]
encoding = utf-8

# Extraction from JavaScript files

[javascript: **.js]
encoding = utf-8
extract_messages = $._, jQuery._
119 changes: 119 additions & 0 deletions invenio_pages/administration/views/pages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2023 CERN.
#
# invenio-administration is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.

"""Invenio administration pages view module."""
from flask_babelex import lazy_gettext as _
from invenio_administration.views.base import (
AdminResourceDetailView,
AdminResourceEditView,
AdminResourceListView,
)


class PageListView(AdminResourceListView):
"""Configuration for pages list view."""

api_endpoint = "/pages"
name = "Pages"
resource_config = "pages_resource"
search_request_headers = {"Accept": "application/json"}
title = "Pages"
category = "Pages"
pid_path = "id"
icon = "file alternate outline"
template = "invenio_pages/administration/page-search.html"

display_search = True
display_delete = False
display_create = False
display_edit = True

item_field_list = {
"url": {"text": _("Url"), "order": 1},
"title": {"text": _("Title"), "order": 2},
"content": {"text": _("Content"), "order": 3},
"template_name": {"text": _("Template Name"), "order": 4},
"description": {"text": _("Description"), "order": 5},
"created": {"text": _("Created"), "order": 6},
"updated": {"text": _("Updated"), "order": 7},
}

search_config_name = "PAGES_SEARCH"
search_facets_config_name = "PAGES_FACETS"
search_sort_config_name = "PAGES_SORT_OPTIONS"


class PageEditView(AdminResourceEditView):
"""Configuration for page edit view."""

name = "pages_edit"
url = "/pages/<pid_value>/edit"
resource_config = "pages_resource"
pid_path = "id"
api_endpoint = "/pages"
title = "Edit Page set"

list_view_name = "Pages"

form_fields = {
"url": {
"order": 1,
"text": _("URL"),
"description": _("Relative path to the page."),
},
"title": {
"order": 2,
"text": _("Title"),
"description": _("Title of the page."),
},
"content": {
"order": 3,
"text": _("Content"),
"description": _("Content displayed by the page."),
"rows": 10,
},
"template_name": {
"order": 4,
"text": _("Template name"),
"description": _("Jinja template used to display the page."),
},
"description": {
"order": 5,
"text": _("Description"),
"description": _("Description of the page"),
},
"created": {"order": 6},
"updated": {"order": 7},
}


class PageDetailView(AdminResourceDetailView):
"""Configuration for page detail view."""

url = "/pages/<pid_value>"
api_endpoint = "/pages"
name = "page-details"
resource_config = "pages_resource"
title = "Page"

display_edit = True
display_delete = False

list_view_name = "Pages"
pid_path = "id"

item_field_list = {
"id": {"text": _("Id"), "order": 1},
"url": {"text": _("Url"), "order": 2},
"title": {"text": _("Title"), "order": 3},
"content": {"text": _("Content"), "order": 4},
"template_name": {"text": _("Template Name"), "order": 5},
"description": {"text": _("Description"), "order": 6},
"created": {"text": _("Created"), "order": 7},
"updated": {"text": _("Updated"), "order": 8},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* This file is part of Invenio.
* Copyright (C) 2023 CERN.
*
* Invenio is free software; you can redistribute it and/or modify it
* under the terms of the MIT License; see LICENSE file for more details.
*/

import PropTypes from "prop-types";
import React, { Component } from "react";
import { Table } from "semantic-ui-react";
import isEmpty from "lodash/isEmpty";
import { Actions } from "@js/invenio_administration";
import { withState } from "react-searchkit";
import { AdminUIRoutes } from "@js/invenio_administration";
import { Formatter } from "@js/invenio_administration";
import _truncate from "lodash/truncate";

class SearchResultItemComponent extends Component {
refreshAfterAction = () => {
const { updateQueryState, currentQueryState } = this.props;
updateQueryState(currentQueryState);
};

render() {
const {
title,
resourceName,
result,
columns,
displayEdit,
displayDelete,
actions,
idKeyPath,
resourceSchema,
listUIEndpoint,
} = this.props;
const resourceHasActions =
displayEdit || displayDelete || !isEmpty(actions);
result.content = _truncate(result.content, { length: 250 });

return (
<Table.Row>
{columns.map(([property, { text, order }], index) => {
return (
<Table.Cell
key={`${text}-${order}`}
data-label={text}
className="word-break-all"
>
{index === 0 && (
<a
href={AdminUIRoutes.detailsView(
listUIEndpoint,
result,
idKeyPath
)}
>
{result[property]}
</a>
)}
{index !== 0 && (
<Formatter
result={result}
resourceSchema={resourceSchema}
property={property}
/>
)}
</Table.Cell>
);
})}
{resourceHasActions && (
<Table.Cell collapsing>
<Actions
title={title}
resourceName={resourceName}
editUrl={AdminUIRoutes.editView(
listUIEndpoint,
result,
idKeyPath
)}
displayEdit={displayEdit}
displayDelete={displayDelete}
actions={actions}
resource={result}
idKeyPath={idKeyPath}
successCallback={this.refreshAfterAction}
listUIEndpoint={listUIEndpoint}
/>
</Table.Cell>
)}
</Table.Row>
);
}
}

SearchResultItemComponent.propTypes = {
title: PropTypes.string.isRequired,
resourceName: PropTypes.string.isRequired,
result: PropTypes.object.isRequired,
columns: PropTypes.array.isRequired,
displayDelete: PropTypes.bool,
displayEdit: PropTypes.bool,
actions: PropTypes.object,
updateQueryState: PropTypes.func.isRequired,
currentQueryState: PropTypes.object.isRequired,
idKeyPath: PropTypes.string.isRequired,
resourceSchema: PropTypes.object.isRequired,
listUIEndpoint: PropTypes.string.isRequired,
};

SearchResultItemComponent.defaultProps = {
displayDelete: false,
displayEdit: true,
actions: {},
};

export const SearchResultItem = withState(SearchResultItemComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* This file is part of Invenio.
* Copyright (C) 2023 CERN.
*
* Invenio is free software; you can redistribute it and/or modify it
* under the terms of the MIT License; see LICENSE file for more details.
*/

import PropTypes from "prop-types";
import React from "react";
import { Table } from "semantic-ui-react";
import isEmpty from "lodash/isEmpty";
import { i18next } from "@translations/invenio_administration/i18next";

export const SearchResultsContainer = ({
results,
columns,
displayEdit,
displayDelete,
actions,
}) => {
const resourceHasActions = displayEdit || displayDelete || !isEmpty(actions);

const columnWidth = {
"Url": 1,
"Title": 2,
"Content": 5,
"Template Name": 3,
"Description": 2,
"Created": 1,
"Updated": 1
}

return (
<Table>
<Table.Header>
<Table.Row>
{columns.map(([property, { text, order }], index) => {
const width = columnWidth[text];
return (
<Table.HeaderCell key={property + order} width={width}>
{text}
</Table.HeaderCell>
);
})}
{resourceHasActions && (
<Table.HeaderCell collapsing>{i18next.t("Actions")}</Table.HeaderCell>
)}
</Table.Row>
</Table.Header>
<Table.Body>{results}</Table.Body>
</Table>
);
};

SearchResultsContainer.propTypes = {
results: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired,
displayEdit: PropTypes.bool,
displayDelete: PropTypes.bool,
actions: PropTypes.object.isRequired,
};

SearchResultsContainer.defaultProps = {
displayDelete: false,
displayEdit: true,
};
Loading