mirror of
https://github.com/Cian-H/iform-invenio.git
synced 2026-08-18 01:12:48 +01:00
Significant overhaul of tooling
This commit is contained in:
@@ -18,8 +18,11 @@ process.
|
||||
|
||||
Once running, visit https://127.0.0.1 in your browser.
|
||||
|
||||
**Note**: The server is using a self-signed SSL certificate, so your browser
|
||||
will issue a warning that you will have to by-pass.
|
||||
**Note**: The server uses a self-signed SSL certificate. You must generate it first by running:
|
||||
```console
|
||||
just generate-dev-certs
|
||||
```
|
||||
Your browser will issue a warning that you will have to by-pass.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
subjects:
|
||||
pid-type: sub
|
||||
schemes:
|
||||
- id: FOS
|
||||
name: Fields of Science and Technology
|
||||
uri: "http://www.oecd.org/science/inno/38235147.pdf"
|
||||
data-file: vocabularies/subjects_oecd_fos.yaml
|
||||
pid-type: sub
|
||||
schemes:
|
||||
- id: FOS
|
||||
name: Fields of Science and Technology
|
||||
uri: "http://www.oecd.org/science/inno/38235147.pdf"
|
||||
data-file: vocabularies/subjects_oecd_fos.yaml
|
||||
# Minimal example vocabularies
|
||||
# can be used for quick testing, or a basis for building your own customized vocabularies.
|
||||
#names:
|
||||
|
||||
@@ -1,96 +1,96 @@
|
||||
- id: ara
|
||||
props:
|
||||
alpha_2: ar
|
||||
alpha_2: ar
|
||||
tags:
|
||||
- macrolanguage
|
||||
- living
|
||||
- macrolanguage
|
||||
- living
|
||||
title:
|
||||
en: Arabic
|
||||
en: Arabic
|
||||
- id: cym
|
||||
props:
|
||||
alpha_2: cy
|
||||
alpha_2: cy
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Welsh
|
||||
en: Welsh
|
||||
- id: deu
|
||||
props:
|
||||
alpha_2: de
|
||||
alpha_2: de
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: German
|
||||
en: German
|
||||
- id: eng
|
||||
props:
|
||||
alpha_2: en
|
||||
alpha_2: en
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: English
|
||||
en: English
|
||||
- id: fra
|
||||
props:
|
||||
alpha_2: fr
|
||||
alpha_2: fr
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: French
|
||||
en: French
|
||||
- id: ita
|
||||
props:
|
||||
alpha_2: it
|
||||
alpha_2: it
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Italian
|
||||
en: Italian
|
||||
- id: nor
|
||||
props:
|
||||
alpha_2: 'no'
|
||||
alpha_2: "no"
|
||||
tags:
|
||||
- macrolanguage
|
||||
- living
|
||||
- macrolanguage
|
||||
- living
|
||||
title:
|
||||
en: Norwegian
|
||||
en: Norwegian
|
||||
- id: roh
|
||||
props:
|
||||
alpha_2: rm
|
||||
alpha_2: rm
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Romansh
|
||||
en: Romansh
|
||||
- id: spa
|
||||
props:
|
||||
alpha_2: es
|
||||
alpha_2: es
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Spanish
|
||||
en: Spanish
|
||||
- id: tur
|
||||
props:
|
||||
alpha_2: tr
|
||||
alpha_2: tr
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Turkish
|
||||
en: Turkish
|
||||
- id: aag
|
||||
props:
|
||||
alpha_2: ''
|
||||
alpha_2: ""
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Ambrak
|
||||
en: Ambrak
|
||||
- id: aah
|
||||
props:
|
||||
alpha_2: ''
|
||||
alpha_2: ""
|
||||
tags:
|
||||
- individual
|
||||
- living
|
||||
- individual
|
||||
- living
|
||||
title:
|
||||
en: Abu' Arapesh
|
||||
en: Abu' Arapesh
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
- affiliations:
|
||||
- name: University of Zurich
|
||||
- name: Humboldt University of Berlin
|
||||
- name: Kaiser Wilhelm Institute for Physics
|
||||
- name: University of Zurich
|
||||
- name: Humboldt University of Berlin
|
||||
- name: Kaiser Wilhelm Institute for Physics
|
||||
family_name: Einstein
|
||||
given_name: Albert
|
||||
id: gnd:118529579
|
||||
identifiers:
|
||||
- identifier: gnd:118529579
|
||||
scheme: gnd
|
||||
- identifier: gnd:118529579
|
||||
scheme: gnd
|
||||
- affiliations:
|
||||
- name: University of Cambridge
|
||||
- name: California Institute of Technology
|
||||
- name: University of Oxford
|
||||
- name: University of Cambridge
|
||||
- name: California Institute of Technology
|
||||
- name: University of Oxford
|
||||
family_name: Hawking
|
||||
given_name: Stephen
|
||||
id: 0000-0002-9079-593X
|
||||
identifiers:
|
||||
- identifier: https://orcid.org/0000-0002-9079-593X
|
||||
scheme: orcid
|
||||
- identifier: https://orcid.org/0000-0002-9079-593X
|
||||
scheme: orcid
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
* Add here all the overridden components of your app.
|
||||
*/
|
||||
|
||||
export const overriddenComponents = {}
|
||||
export const overriddenComponents = {};
|
||||
|
||||
@@ -17,8 +17,15 @@ services:
|
||||
- "INVENIO_SEARCH_HOSTS=['search:9200']"
|
||||
- "INVENIO_SECRET_KEY=CHANGE_ME"
|
||||
- "INVENIO_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://i-form-data-repository:i-form-data-repository@db/i-form-data-repository"
|
||||
- "INVENIO_WSGI_PROXIES=2"
|
||||
- "INVENIO_WSGI_PROXIES=1"
|
||||
- "INVENIO_RATELIMIT_STORAGE_URL=redis://cache:6379/3"
|
||||
- "INVENIO_S3_ACCESS_KEY_ID=${INVENIO_S3_ACCESS_KEY_ID}"
|
||||
- "INVENIO_S3_SECRET_ACCESS_KEY=${INVENIO_S3_SECRET_ACCESS_KEY}"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
frontend:
|
||||
build:
|
||||
context: ./docker/nginx/
|
||||
@@ -28,6 +35,11 @@ services:
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:8080:80"
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:8443:443"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
cache:
|
||||
image: docker.io/library/redis:7
|
||||
restart: "unless-stopped"
|
||||
@@ -35,14 +47,26 @@ services:
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:6379:6379"
|
||||
db:
|
||||
image: docker.io/library/postgres:14.13
|
||||
image: registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-14.11-0
|
||||
restart: "unless-stopped"
|
||||
environment:
|
||||
- "POSTGRES_USER=i-form-data-repository"
|
||||
- "POSTGRES_PASSWORD=i-form-data-repository"
|
||||
- "POSTGRES_DB=i-form-data-repository"
|
||||
- "PGBACKREST_REPO1_TYPE=s3"
|
||||
- "PGBACKREST_REPO1_S3_BUCKET=${INVENIO_S3_BUCKET_NAME}"
|
||||
- "PGBACKREST_REPO1_S3_ENDPOINT=${INVENIO_S3_ENDPOINT_URL}"
|
||||
- "PGBACKREST_REPO1_S3_KEY=${INVENIO_S3_ACCESS_KEY_ID}"
|
||||
- "PGBACKREST_REPO1_S3_KEY_SECRET=${INVENIO_S3_SECRET_ACCESS_KEY}"
|
||||
- "PGBACKREST_REPO1_S3_REGION=${INVENIO_S3_REGION_NAME}"
|
||||
- "PGBACKREST_REPO1_PATH=/backup/meta_db"
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:5432:5432"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
pgadmin:
|
||||
image: docker.io/dpage/pgadmin4:6
|
||||
restart: "unless-stopped"
|
||||
@@ -66,7 +90,7 @@ services:
|
||||
# settings only for development. DO NOT use in production!
|
||||
- bootstrap.memory_lock=true
|
||||
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
- "OPENSEARCH_INITIAL_ADMIN_PASSWORD=guekxe3mvqieke1!%&ieIADE"
|
||||
- "OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD:-guekxe3mvqieke1!%&ieIADE}"
|
||||
- "DISABLE_INSTALL_DEMO_CONFIG=true"
|
||||
- "DISABLE_SECURITY_PLUGIN=true"
|
||||
- "discovery.type=single-node"
|
||||
@@ -82,6 +106,11 @@ services:
|
||||
ports:
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:9200:9200"
|
||||
- "${DOCKER_SERVICES_IP_BIND:-127.0.0.1}:9600:9600"
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "50m"
|
||||
max-file: "3"
|
||||
opensearch-dashboards:
|
||||
image: docker.io/opensearchproject/opensearch-dashboards:2.17.1
|
||||
ports:
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
test.crt
|
||||
test.key
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"Servers": {
|
||||
"1": {
|
||||
"Name": "i-form-data-repository-db",
|
||||
"Group": "Servers",
|
||||
"Host": "i-form-data-repository-db-1",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "postgres",
|
||||
"Username": "i-form-data-repository",
|
||||
"SSLMode": "prefer"
|
||||
"Servers": {
|
||||
"1": {
|
||||
"Name": "i-form-data-repository-db",
|
||||
"Group": "Servers",
|
||||
"Host": "i-form-data-repository-db-1",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "postgres",
|
||||
"Username": "i-form-data-repository",
|
||||
"SSLMode": "prefer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,46 @@
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import json
|
||||
|
||||
|
||||
def main():
|
||||
# 1. Ensure ga directories exist and have translations.json
|
||||
packages = [
|
||||
'invenio_communities',
|
||||
'invenio_search_ui',
|
||||
'invenio_app_rdm',
|
||||
'invenio_requests',
|
||||
'invenio_jobs',
|
||||
'invenio_rdm_records',
|
||||
'invenio_administration'
|
||||
"invenio_communities",
|
||||
"invenio_search_ui",
|
||||
"invenio_app_rdm",
|
||||
"invenio_requests",
|
||||
"invenio_jobs",
|
||||
"invenio_rdm_records",
|
||||
"invenio_administration",
|
||||
]
|
||||
bases = [
|
||||
'/opt/invenio/src/.venv/lib/python3.12/site-packages',
|
||||
'/opt/invenio/var/instance/assets/translations'
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages",
|
||||
"/opt/invenio/var/instance/assets/translations",
|
||||
]
|
||||
for pkg in packages:
|
||||
for base in bases:
|
||||
for root, dirs, files_in_dir in os.walk(base):
|
||||
if root.endswith('messages') and pkg in root:
|
||||
ga_dir = os.path.join(root, 'ga')
|
||||
if root.endswith("messages") and pkg in root:
|
||||
ga_dir = os.path.join(root, "ga")
|
||||
os.makedirs(ga_dir, exist_ok=True)
|
||||
json_path = os.path.join(ga_dir, 'translations.json')
|
||||
json_path = os.path.join(ga_dir, "translations.json")
|
||||
if not os.path.exists(json_path) or os.path.getsize(json_path) <= 2:
|
||||
with open(json_path, 'w') as fp:
|
||||
fp.write('{}')
|
||||
with open(json_path, "w") as fp:
|
||||
fp.write("{}")
|
||||
print(f"Created empty translations.json: {json_path}")
|
||||
|
||||
# 2. Copy the actual compiled translations if they exist
|
||||
copies = [
|
||||
(
|
||||
'/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_communities/assets/semantic-ui/translations/invenio_communities/messages/ga/translations.json',
|
||||
'/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json'
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_communities/assets/semantic-ui/translations/invenio_communities/messages/ga/translations.json",
|
||||
"/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json",
|
||||
),
|
||||
(
|
||||
'/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_search_ui/assets/semantic-ui/translations/invenio_search_ui/messages/ga/translations.json',
|
||||
'/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json'
|
||||
)
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages/invenio_search_ui/assets/semantic-ui/translations/invenio_search_ui/messages/ga/translations.json",
|
||||
"/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json",
|
||||
),
|
||||
]
|
||||
for src, dst in copies:
|
||||
if os.path.exists(src):
|
||||
@@ -48,57 +49,68 @@ def main():
|
||||
print(f"Copied compiled translations: {src} -> {dst}")
|
||||
|
||||
# 3. Extract app_rdm translations from global ga.json
|
||||
global_ga = '/opt/invenio/var/instance/translations/ga.json'
|
||||
app_rdm_dst = '/opt/invenio/var/instance/assets/translations/invenio_app_rdm/messages/ga/translations.json'
|
||||
global_ga = "/opt/invenio/var/instance/translations/ga.json"
|
||||
app_rdm_dst = "/opt/invenio/var/instance/assets/translations/invenio_app_rdm/messages/ga/translations.json"
|
||||
if os.path.exists(global_ga):
|
||||
try:
|
||||
with open(global_ga, 'r') as fp:
|
||||
with open(global_ga, "r") as fp:
|
||||
ga_data = json.load(fp)
|
||||
app_rdm_data = ga_data.get('invenio_app_rdm', {})
|
||||
app_rdm_data = ga_data.get("invenio_app_rdm", {})
|
||||
os.makedirs(os.path.dirname(app_rdm_dst), exist_ok=True)
|
||||
with open(app_rdm_dst, 'w') as fp:
|
||||
with open(app_rdm_dst, "w") as fp:
|
||||
json.dump(app_rdm_data, fp, indent=2)
|
||||
print(f"Extracted invenio_app_rdm translations to {app_rdm_dst}")
|
||||
|
||||
|
||||
# Also extract search_ui and communities if they were not copied
|
||||
search_ui_dst = '/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json'
|
||||
if 'invenio_search_ui' in ga_data:
|
||||
search_ui_dst = "/opt/invenio/var/instance/assets/translations/invenio_search_ui/messages/ga/translations.json"
|
||||
if "invenio_search_ui" in ga_data:
|
||||
os.makedirs(os.path.dirname(search_ui_dst), exist_ok=True)
|
||||
with open(search_ui_dst, 'w') as fp:
|
||||
json.dump(ga_data['invenio_search_ui'], fp, indent=2)
|
||||
with open(search_ui_dst, "w") as fp:
|
||||
json.dump(ga_data["invenio_search_ui"], fp, indent=2)
|
||||
print(f"Extracted invenio_search_ui translations to {search_ui_dst}")
|
||||
|
||||
communities_dst = '/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json'
|
||||
if 'invenio_communities' in ga_data:
|
||||
|
||||
communities_dst = "/opt/invenio/var/instance/assets/translations/invenio_communities/messages/ga/translations.json"
|
||||
if "invenio_communities" in ga_data:
|
||||
os.makedirs(os.path.dirname(communities_dst), exist_ok=True)
|
||||
with open(communities_dst, 'w') as fp:
|
||||
json.dump(ga_data['invenio_communities'], fp, indent=2)
|
||||
print(f"Extracted invenio_communities translations to {communities_dst}")
|
||||
with open(communities_dst, "w") as fp:
|
||||
json.dump(ga_data["invenio_communities"], fp, indent=2)
|
||||
print(
|
||||
f"Extracted invenio_communities translations to {communities_dst}"
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error extracting translations: {e}")
|
||||
|
||||
# 4. Patch all _generatedTranslations.js files
|
||||
files = glob.glob('/opt/invenio/src/.venv/lib/python3.12/site-packages/**/_generatedTranslations.js', recursive=True) + glob.glob('/opt/invenio/var/instance/assets/**/_generatedTranslations.js', recursive=True)
|
||||
files = glob.glob(
|
||||
"/opt/invenio/src/.venv/lib/python3.12/site-packages/**/_generatedTranslations.js",
|
||||
recursive=True,
|
||||
) + glob.glob(
|
||||
"/opt/invenio/var/instance/assets/**/_generatedTranslations.js", recursive=True
|
||||
)
|
||||
for f in files:
|
||||
with open(f, 'r') as fp:
|
||||
with open(f, "r") as fp:
|
||||
content = fp.read()
|
||||
if 'TRANSLATE_GA' not in content:
|
||||
lines = content.split('\n')
|
||||
if "TRANSLATE_GA" not in content:
|
||||
lines = content.split("\n")
|
||||
last_import = -1
|
||||
for i, line in enumerate(lines):
|
||||
if line.startswith('import '):
|
||||
if line.startswith("import "):
|
||||
last_import = i
|
||||
if last_import != -1:
|
||||
lines.insert(last_import + 1, 'import TRANSLATE_GA from "./ga/translations.json";')
|
||||
content = '\n'.join(lines)
|
||||
if 'export const translations = {' in content:
|
||||
content = content.replace(
|
||||
'export const translations = {',
|
||||
'export const translations = {\n ga: { translation: TRANSLATE_GA },'
|
||||
lines.insert(
|
||||
last_import + 1,
|
||||
'import TRANSLATE_GA from "./ga/translations.json";',
|
||||
)
|
||||
with open(f, 'w') as fp:
|
||||
content = "\n".join(lines)
|
||||
if "export const translations = {" in content:
|
||||
content = content.replace(
|
||||
"export const translations = {",
|
||||
"export const translations = {\n ga: { translation: TRANSLATE_GA },",
|
||||
)
|
||||
with open(f, "w") as fp:
|
||||
fp.write(content)
|
||||
print(f"Patched _generatedTranslations.js: {f}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
|
||||
#
|
||||
# Registration
|
||||
#
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"invenio_search_ui": {
|
||||
"invenio_search_ui:Search records...": "Cuardaigh taifid..."
|
||||
},
|
||||
"invenio_communities": {
|
||||
"invenio_communities:You are not a member of any community.": "Níl tú mar bhall d'aon phobal.",
|
||||
"invenio_communities:There are no new communities.": "Níl aon phobail nua ann.",
|
||||
"invenio_communities:My Communities": "Mo Phobail",
|
||||
"invenio_communities:New Communities": "Pobail Nua",
|
||||
"invenio_communities:Search communities...": "Cuardaigh pobail...",
|
||||
"invenio_communities:Organize, curate and share your research. Ideal for research projects, departments or temporary working groups.": "Eagraigh, coimeád agus comhroinn do chuid taighde. Ideal do thionscadail taighde, ranna nó grúpaí oibre sealadacha."
|
||||
},
|
||||
"invenio_app_rdm": {
|
||||
"invenio_app_rdm:Search records...": "Cuardaigh taifid...",
|
||||
"invenio_app_rdm:Search in my communities": "Cuardaigh i mo phobail",
|
||||
"invenio_app_rdm:Search in my communities...": "Cuardaigh i mo phobail...",
|
||||
"invenio_app_rdm:My communities": "Mo phobail",
|
||||
"invenio_app_rdm:Search in my uploads...": "Cuardaigh i mo chuid uaslódálacha...",
|
||||
"invenio_app_rdm:My uploads": "Mo chuid uaslódálacha",
|
||||
"invenio_app_rdm:Overview": "Foramharc",
|
||||
"invenio_app_rdm:Uploads": "Uaslódálacha"
|
||||
}
|
||||
"invenio_search_ui": {
|
||||
"invenio_search_ui:Search records...": "Cuardaigh taifid..."
|
||||
},
|
||||
"invenio_communities": {
|
||||
"invenio_communities:You are not a member of any community.": "Níl tú mar bhall d'aon phobal.",
|
||||
"invenio_communities:There are no new communities.": "Níl aon phobail nua ann.",
|
||||
"invenio_communities:My Communities": "Mo Phobail",
|
||||
"invenio_communities:New Communities": "Pobail Nua",
|
||||
"invenio_communities:Search communities...": "Cuardaigh pobail...",
|
||||
"invenio_communities:Organize, curate and share your research. Ideal for research projects, departments or temporary working groups.": "Eagraigh, coimeád agus comhroinn do chuid taighde. Ideal do thionscadail taighde, ranna nó grúpaí oibre sealadacha."
|
||||
},
|
||||
"invenio_app_rdm": {
|
||||
"invenio_app_rdm:Search records...": "Cuardaigh taifid...",
|
||||
"invenio_app_rdm:Search in my communities": "Cuardaigh i mo phobail",
|
||||
"invenio_app_rdm:Search in my communities...": "Cuardaigh i mo phobail...",
|
||||
"invenio_app_rdm:My communities": "Mo phobail",
|
||||
"invenio_app_rdm:Search in my uploads...": "Cuardaigh i mo chuid uaslódálacha...",
|
||||
"invenio_app_rdm:My uploads": "Mo chuid uaslódálacha",
|
||||
"invenio_app_rdm:Overview": "Foramharc",
|
||||
"invenio_app_rdm:Uploads": "Uaslódálacha"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user