Feature Wiki

Information about planned and released features

Tabs

Named Placeholder in Translations

1 Initial Problem

When creating language entries which contain changing values within their text body, it is very common to use generic placeholders such as %s for words and %d for decimals. This is due to the fact that the Language Service does not itself provide a function to replace placeholders in language entries - most developers have (non-verbally) agreed to use the light-weight and easy-to-use PHP function sprintf. This works pretty much ok if there is only one placeholder in an entry or within the main languages English and German.

Problems occour when our language maintainers have to translate sentences with all their grammatical subtleties, but are forced to stick to a particular order of placeholders. The placeholders above lack the abillity to be positioned freely within the translated entries. Therefore, the order in which the placeholders appear within the German and English entries must be strictly adhered to. This can make translation into other languages very challenging, especially those with a different language stem and sentence structures. Even when translating from German into English, which are closely related, this can become a problem, as our English language maintainer can attest.

For example: In an imaginary case for the translation of the real language variable "common#:#msg_obj_exists_in_folder#:#The object %s already exists in the folder %s." it might be appropriate for a specific Language to always state the location at the beginning of the sentence. Most of the time, there is always some sort of way to formulate a sentence around it. But this often requires strange sentence structures or simply more work.

There is a notation next to %s and %d to indicate the original order of the code. To use this notation and also place the second before the first placeholder we would write the format string like this instead: Foo %2$s Bar %1$sFoo %2$s Bar %1$s or mixed Foo %2$d Bar %1$s. This would be the solution to the issue mentioned above but it still has some flaws. First the typical translator is not a developer and has never heard of sprintf's specialities (this was also new to me as a developer, why i had to add this paragraph afterwards :D ). Also a developer, who is also not aware of this notation or simply does not think about it, would change the order within his code and the language text when rephrasing his language entry and invalidate all translations by doing so. Finally, this method of notation is unnecessarily complicated, since you first have to find out the original order from the German or English text and keep to it.

As of July 2023, this affects 155 language variables in the English language file.  This can be reproduced by the following bash command: grep -E "%([0-9]+\\$)?[bcdeEfFgGhHosuxX].*%([0-9]+\\$)?[bcdeEfFgGhHosuxX]" ilias_en.lang. It lists every occourences of at least two sprintf specifiers in a language entry.

2 Conceptual Summary

In order for translators to be able to translate the sentences with more freedom and with no special dev knowledge, it is necessary to replace the unnamed placeholder to named ones. For example, to continue with the example above "common#:#msg_obj_exists_in_folder#:#The object @object already exists in the folder @folder.". This way the translator is able to place the location at the beginning of his sentence and the subject to the end (As far as I am aware, no such language exists, but you get the point).

To encourage the developers to use it, it should be offered as an easy-to-use and high-performance functionality via the language service. The gathering of a translation for example could look as such: $lng->txtf("msg_obj_exists_in_folder", ["object" => $foo, "folder" => $bar]);. Internally the PHP core functionality strtr could help to implement this efficiently.

Furthermore there should be guideline for developer to define do's and dont's. For example:

  1. Don't use sprintf anymore.
  2. Don't simply rename placeholder. Rename them in every translation.
  3. If placeholders need to be removed or added, the entries from the other languages should be removed or commented on so that translators can adapt the entry.

As a bonus, further improvements could be implemented using this new functionallity, such as:

  • automatically translate \ilDate and \ilDateTime into the correct localized date formats
  • use commas and dots within the correct localized number format to make long numbers more easily readable
  • correctly formatted names by simply passing to an\ilObjUser object.

I see the refactoring of the 155 existing cases as optional. It should not be a complex task in itself, but the communication and project managment could get out of hand because it affects many different maintainers. An adaptation on demand for special cases should be sufficient, assuming that the translators are aware of the possibility.
(or just give a developer absolute power of authority over all modules for 3 days to change this muhaha)

If this feature request is not accepted, I still recommend a guideline for developers on how to handle sprintf placeholders to preserve translations and a guide for translators on how to handle sprintf placeholders.

3 User Interface Modifications

3.1 List of Affected Views

  • None

3.2 User Interface Details

  • None

3.3 New User Interface Concepts

None

3.4 Accessibility Implications

This feature has the potential to make some translations more readable in other languages.

4 Technical Information

{ The maintainer has to provide necessary technical information, e.g. dependencies on other ILIAS components, necessary modifications in general services/architecture, potential security or performance issues. }

5 Privacy

{ Please list all personal data that will need to be stored or processed to implement this feature. For each date give a short explanation why it is necessary to use that date. }

6 Security

{ Does the feature include any special security relevant changes, e.g. the introducion of new endpoints or other new possible attack vectors. If yes, please explain these implications and include a commitment to deliver a written security concept as part of the feature development. This concept will need an additional approvement by the JourFixe. }

7 Contact

  • Author of the Request: Wolf, Fabian [fwolf]
  • Maintainer: {Please add your name before applying for an initial workshop or a Jour Fixe meeting.}
  • Implementation of the feature is done by: {The maintainer must add the name of the implementing developer.}

8 Funding

If you are interest in funding this feature, please add your name and institution to this list.

9 Discussion

10 Implementation

{ The maintainer has to give a description of the final implementation and add screenshots if possible. }

Test Cases

Test cases completed at {date} by {user}

  • {Test case number linked to Testrail} : {test case title}

Privacy

Information in privacy.md of component: updated on {date} by {user} | no change required

Approval

Approved at {date} by {user}.

Last edited: 20. Aug 2024, 17:30, Wolf, Fabian [fwolf]