Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Warning
titleWARNING - Still under review

The proposed approach is still under review - there are still considerable technical hurdles to overcome in this area of work.

Introduction

Prior to DSpace 7, the DSpace XML and JSP User interfaces had different catalogs of interface messages. Unified on a single user interface, the DSpace community is transitioning to a single catalog of interfaces messages and better tools for translators.

...

Contributing to translations only requires a Github and a DuraSpace wiki (free) Github account. Head over to www.github.com to create a free Github account.Accounts for the DuraSpace wiki are free as well and can be requested in an email to sysadmin@duraspace.org, indicating that you wish to contribute to DSpace 7 Translations and get started.

Make yourself familiar with the new json5 catalog of DSpace messages

2019-10-29 State of development

...

The following video walks you through the contribution process:

Widget Connector
width800
urlhttps://www.youtube.com/watch?v=zQ199ywN_kY

2020-05-18 Development status

This documentation page has been updated to reflect that the language catalogs have moved from /resources/i18n to /src/assets/i18n and that sync-i18n-files.js has now become a typescript file.

Instructions to start the script have been updated.

Early DSpace 7 Documentation is now available at Multilingual Support

Volunteer!

Please list your name, email address alongside any of the languages to which you wish to contribute. Also feel free to join the channel #translation on the DuraSpace DSpace Slack for assistance and discussion around DSpace 7 translations. 

Dutch (nl.json5)

Bram Luyten - bram@atmire.comMarina Muilwijk 

German (de.json5)

Claudia Jürgen - claudia.juergen@tu-dortmund.de 

Translator documentation

Translation files (.po)

Comments - #

All lines in the translation files that start with # are comments, either aimed at helping developers or helping translators.

#: at the start of a line is a source reference, aimed at making it clear where in the source code this message IS or WAS used. Because the original po files were migrated from another, json based format, the old JSON keys have been added as source references, to make it clear where the message originally came from in the previous format.

Normal key / msgid examples

For most keys that need to be translated, the English original is part of the DSpace Angular source code. This original is then used as the msgid

As a translator, you add the translation into the msgstr variable.

As demonstrated in the example below, you are required to wrap your translation in double quotes.

Code Block
languagebash
titleBasic translation example
#: .item.edit.withdraw.description
msgid "Are you sure this item should be withdrawn from the archive?"
msgstr "Ben je zeker dat je dit item wil terugtrekken uit het archief?"

Following multi-line example shows that both the original key, as well as the translation, can be split over multiple lines.

Code Block
languagebash
titleMulti-line key and translation example
#: .submission.sections.upload.info
msgid ""
"Here you will find all the files currently in the item. You can update the "
"file metadata and access conditions or <strong>upload additional files just "
"dragging & dropping them everywhere in the page</strong>"
msgstr ""
"Hier vind je alle bestanden momenteel opgeladen in het item. Je kan hier de "
"bestands metadata en toegangsvoorwaarden aanpassen. Je kan ook <strong>extra"
"bestanden toevoegen door ze eender waar naar de pagina te slepen</strong>"

Because double quote is the special character that starts or ends a message, you need to prefix double quotes with \ if you want them to appear in the actual message.

Likewise, as the previous just explained that \ can be used to escape characters, you also need to escape \ itself if you want it to appear in the message.

Code Block
languagebash
titleEscaping of double quotes example
#: .submission.workflow.generic.delete-help
msgid ""
"If you would to discard this item, select \"Delete\".  You will then be "
"asked to confirm it."
msgstr ""
"If you would to discard this item, select \"Delete\".  You will then be "
"asked to confirm it."

Dynamic key example

In parts of the DSpace Angular code, a list of very similar objects is being built and displayed in the user interface, for example, the search filters. 

These similar objects all need different labels in the user interface:

  • search.filters.filter.author.head
  • search.filters.filter.dateissued.head
  • ...

Contrary to the normal keys that are discussed higher on this page, they keys are dynamically built in the code, meaning that the developer has no opportunity to put the English string into the code, unless he or she would hard-code a static list of those similar objects. If this sounds too abstract, look at the snippet of angular component code that puts these search filters in the page:

Code Block
languagexml
<h5 class="d-inline-block mb-0">{{'search.filters.filter.' + filter.name + '.head'| translate}}</h5>

So to deal with these kinds of occurences, we are currently still using the (old) en.json key entries for those type of messages, in the en.po file, for example:

Code Block
languagebash
#. ENGLISH KEY: "Author"
#: .search.filters.filter.author.head
msgid "search.filters.filter.author.head"
msgstr "Author"

Notice how here, that the English translation is also added into the comments, because msgid needs to hold the key in order for the translation to work.

The Angular DSpace 7 message catalog (dspace.pot)

The format of the dspace.pot catalog file, is very similar to the format of the translations. 

The main difference is that this file does not contain actual translated strings (msgstr), because it serves as the authoritative catalog of the source messages, without translations.

Background reading

The PO Format

GNU gettext utilities

Developer How-to

Escaping

In Angular files (.html, .ts, ...) you need to escape

Code Block
{{ 'copyright © 2002-{'+'{ year }'+'}' | translate:{year : dateObj | date:'y'} }}

In .po/.pot files you need to escape

  • Double quotes (") with \
  • ...

Locating keys that have not been replaced

If you execute following command in the angular source directory, you get a list of keys that have not yet been replaced.

Code Block
languagebash
titleGrep command for identifying keys that have not yet been replaced
grep -snRHIiE "'.*\.[^\s]+\.[^']+' \| translate" *

Sample output looks like:

Spanish (es.json5)

Maria Fernanda Ruiz

Eva Braña Arvo Consultores for Version 7.3 )

Emilio Lorenzo (Arvo Consultores for Version 7.3 )

Brazilian Portuguese (pt-BR.json5)

Vítor Silvério Rodrigues

French (fr.json5)

David Cavrenne [Atmire]

Marie-Hélène Vézina

Finnish (fi.json5)

Reeta Kuuskoski

Latvian (lv.json5)

Denijs Balodis

Polish (pl.json5)

Michał Dykas  (PCG Academia)

Translator documentation

The authoritative English master file (en.json5)

The catalogs can be found in src/assets/i18n

Code Block
titleen.json5 example section
"submission.workflow.tasks.claimed.reject.reason.submit": "Reject item",

"submission.workflow.tasks.claimed.reject.reason.title": "Reason",

"submission.workflow.tasks.claimed.reject.submit": "Reject",

"submission.workflow.tasks.claimed.reject_help": "If you have reviewed the item and found it is <strong>not</strong> suitable for inclusion in the collection, select \"Reject\".  You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and resubmit.",

Translations (for example, nl.json5)

In order to allow automated syncing with changes in the English master catalog, and to make it clear to all translators what the original source of the message was, the English original is copied as a comment into the translated files

Code Block
languagejs
titlenl.json5 example section
// "404.link.home-page": "Take me to the home page",
"404.link.home-page": "Terug naar de homepagina",
  
// "404.page-not-found": "page not found",
"404.page-not-found": "Pagina niet gevonden",
  
// "admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.",
// TODO New key - Add a translation
"admin.registries.bitstream-formats.create.failure.content": "An error occurred while creating the new bitstream format.",

When new keys are introduced, TODO messages are automatically added to the catalogs of other languages.

Starting a new language translation from scratch

1. Create an empty file in resources/i18n and give it the two letter iso code of your language as the filename, for example nl.json5 or fr.json5

2. Preload your new catalog with all the messages in the en.json5 catalog by executing the sync-i18n-files.ts script, for which you can find more detailed documentation lower on this page. Assuming you are in /src/assets/i18n, you can execute:

Code Block
yarn run sync-i18n -s en.json5 -i -t fr.json5

or

Code Block
ts-node --project ../../../tsconfig.ts-node.json ../../../scripts/sync-i18n-files.ts -s en.json5 -i -t fr.json5

where en.json5 is the "source" language file where the original keys will be retrieved, and fr.json5 is the catalog of the new language for which you want to start a translation. 

The file should now be filled with all of the English messages, that are now present both as comments, as well as message, for you to translate.

3. Translate as many messages as you can. For every message you translate, remove the TODO comment from the catalog.

4. Activate the new language in ./src/config/default-app-config.ts (look for the "LangConfig[]" array)

Code Block
languages: LangConfig[] = [
  ...
  { code: 'nl', label: 'Nederlands', active: true},
  ...
];

Where code is the two letter code for your language, also used as the filename for your translated catalog. 

Label is the name of your language, written in that language.

Active set to true, so the language is visible in the language selector on the frontpage.

Validating your file with the json5 validator

If you have the DSpace 7 UI running locally, including the yarn tooling to start it up, there is a handy command line tool to validate your new translation. For example, to validate the Spanish file "es.json5", you can execute:

Code Block
titlejson5 validate
yarn json5 --validate ./src/assets/i18n/es.json5

Examples of possible errors you might get:

Code Block
JSON5: invalid character 'R' at 1574:179

1574 indicates the line number, and 179 is the 179th character on that line.

This particular mistake occurred where there was an extra space between \ and " in the \" combination used to escape the "

Checking your files syntax via "lint"

Lint is a tool we use to ensure files are correctly formatted, and have no extra characters (e.g. extra spaces at the end of each line can make the file large in size, which take longer for users to download).  This simple command will check your file's syntax (run this from the root folder):

Code Block
yarn lint --lint-file-patterns src/assets/i18n/*.json5

(NOTE: Warnings shown by lint can be ignored.  Errors are the only thing that require cleanup)


If that throws errors, most can be automatically cleaned up by adding "--fix" to the same command:

Code Block
yarn lint --lint-file-patterns src/assets/i18n/*.json5 --fix


NOTE: currently, "--fix" is unable to add missing commas on the end of each line.  Every new line (which is not a comment) MUST end in a comma.  However, if you have a missing comma, you'll see an error like this:

Code Block
# This error is a sign that you have a missing comma on the line just BEFORE [some translation key]
Parsing error: Unexpected token [some translation key]


Your first translation pull request!

Once you have your first translation, in your dspace-angular repository on your account on Github, you can send these translations in as a pull request. Following screenshots provide clarification:

Overview of your branches, where you can start the pull request. This is at https://github.com/bram-atmire/dspace-angular/branches where "bram-atmire" is changed by your own user name.

Image Added

When you make a pull request, make sure it goes to the "base repository" DSpace/dspace-angular, into the master branch

Image Added

If you experience any difficulties with this, people are ready to help you on #translation in the DuraSpace slack

Developer i18n How-to

When you create new keys, update existing keys or the meaning of existing messages, keep the following in mind.

Escaping

In the message catalogs, double quotes have to be escaped with \

Code Block
"submission.workflow.tasks.claimed.approve_help": "If you have reviewed the item and it is suitable for inclusion in the collection, select \"Approve\"."

Syncing existing translations with changes to en.json5

Whenever you make one of following changes to en.json5:

  • Introduce new keys & messages
  • Change an existing key
  • Change an existing message

Please run the node script: /scripts/sync-i18n-files.ts.

There are two ways to run this script:

  • yarn run sync-i18n
  • ts-node --project ../../../tsconfig.ts-node.json ../../../scripts/sync-i18n-files.ts ==> assuming that you execute this while you are in /src/assets/i18n

The results of your changes will be reflected in the catalogs of the other languages, so translators can pick up the work to:

  • Provide translations for the new keys you just introduced
  • Update existing translations in case you changed the message for an existing key

By default, the execution of sync-i18n-files.ts will:

  • look at en.json5 as the authoritative source file
  • will look at all catalogs present in /src/assets/i18n/ as target files to sync up with the latest changes in source.
  • will execute these changes in-place, meaning that no backup etc is taken of the translation before the sync

If you want to alter this behaviour, you can:

  • specify a different source file using -s
  • specify a different target file using -t
  • specify another output file using -o in case you want to avoid in place edit

...

languagebash

...

Future work

ICU Expressions and Pluralization

...

Together, we aim to release as many, as complete translations as possible, as part of the official DSpace 7.0 release.

Grep commands for identifying keys, if we ever want to replace them with the English string again

Because we are currently keeping message keys, there is no immediate use for identification of keys to replace with the English strings. But for future use, this might still come in handy:

If you execute following command in the angular source directory, you get a list of keys that have not yet been replaced.

Code Block
languagebash
titleGrep command for identifying keys that have not yet been replaced
grep -snRHIiE "'.*\.[^\s]+\.[^']+' \| translate" *

Sample output looks like:

Code Block
languagebash
app/+community-page/delete-community-page/delete-community-page.component.html:5: <h2 id="header" class="border-bottom pb-2">{{ 'community.delete.head' | translate
app/+community-page/delete-community-page/delete-community-page.component.html:7: <p class="pb-2">{{ 'community.delete.text' | translate:{ dso: dso.name } }}</p>
app/+community-page/delete-community-page/delete-community-page.component.html:12: <button class="btn btn-primary" (click)="onCancel(dso)">{{'community.delete.cancel' | translate}}
app/+community-page/edit-community-page/edit-community-page.component.html:4: <h2 id="header" class="border-bottom pb-2">{{ 'community.edit.head' | translate }}</h2>

Background reading

The PO Format

GNU gettext utilities