-
Notifications
You must be signed in to change notification settings - Fork 140
Split developer localization info out of the translator page #543
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
Draft
Copilot
wants to merge
2
commits into
master
Choose a base branch
from
copilot/split-developer-info-translators-page
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
104 changes: 104 additions & 0 deletions
104
docs/technical-reference/developer-guide-to-localization.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| --- | ||
| id: developer-guide-to-localization | ||
| title: Developer guide to localization | ||
| sidebar_label: Localizing OpenRefine | ||
| --- | ||
|
|
||
| This page explains how developers should handle localization when writing or modifying OpenRefine's front end and back end. For information on contributing translations, see [Translate OpenRefine's interface](translating-ui). | ||
|
|
||
| ## Translation format {#translation-format} | ||
|
|
||
| Localized strings are entered in a `.json` file, one per language. They are located in the folder `main/webapp/modules/core/langs/` in a file named `translation-xx.json`, where `xx` is the language code (i.e. `fr` for French). | ||
|
|
||
| ### Simple case of localized string {#simple-case-of-localized-string} | ||
| This is an example of a simple string, with the start of the JSON file. This example is for French. | ||
| ``` | ||
| { | ||
| "name": "Français", | ||
| "core-index/help": "Aide", | ||
| (… more lines) | ||
| } | ||
| ``` | ||
|
|
||
| So the key `core-index/help` will render as `"Aide"` in French. | ||
|
|
||
| ### Localization with a parameterized value {#localization-with-a-parameterized-value} | ||
| In this example, the name of the column (represented by `$1` in this example), will be substituted with the string of the name of the column. | ||
|
|
||
| `"core-facets/edit-facet-title": "Cliquez ici pour éditer le nom de la facette\nColonne : $1",` | ||
|
|
||
| ### Localization with a singular/plural value {#localization-with-a-singularplural-value} | ||
|
|
||
| In this example, one of the parameters will have a different string depending on whether the value is 1 or another value. The string for page, the second parameter `$2`, will have an « s » or not depending on the value of `$2`. | ||
|
|
||
| `"core-views/goto-page": "$1 de $2 {{plural:$2|page|pages}}"` | ||
|
|
||
| #### Languages with more than two plural forms {#languages-with-more-plural-forms} | ||
|
|
||
| Some languages have more than two plural forms. For example, Russian has three forms (one, few, many) and Arabic has six (zero, one, two, few, many, other). The `{{plural:$n|...}}` syntax supports these through [CLDR plural rules](https://cldr.unicode.org/index/cldr-spec/plural-rules). | ||
|
|
||
| You can specify named CLDR keyword forms: | ||
|
|
||
| ``` | ||
| {{plural:$1|one=singular form|few=few form|many=many form|other=default form}} | ||
| ``` | ||
|
|
||
| The English default strings should use the simple `one|other` positional syntax. Translators for languages with more complex plural rules should use the named keyword syntax in their translation files. | ||
|
|
||
| ## Front-end development {#front-end-development} | ||
|
|
||
| The OpenRefine front end has been localized using the [Wikimedia jquery.i18n library](https://github.com/wikimedia/jquery.i18n). The localized text is stored in a JSON dictionary on the server and retrieved with a new OpenRefine command. | ||
|
|
||
| ### Adding a new string {#adding-a-new-string} | ||
|
|
||
| There should be no hard-coded language strings in the HTML or JSON used for the front end. If you need a new string, first check the existing strings to make sure there isn't an equivalent string, **in an equivalent context**, that you can reuse. Context is important because it can affect how the same literal English text is translated. This cuts down on the amount of text which needs to be translated. | ||
|
|
||
| Strings should be entire sentences or phrases and should include substitution variables for any parameters. Do not concatenate strings in either Java or JavaScript (or implicitly by laying them out in a specific order in the HTML). So, instead of `"You have " + count + " row(s)"` (or worse `count != 1 ? " rows" : " row"`), internationalize everything together so that it can be translated taking into account word ordering and plurals for different languages, ie `"You have $1 {{plural:$1|row|rows}}"`, passing the parameter(s) into the `$.i18n` call. | ||
|
|
||
| This is especially important for non-Indo-European languages, where word order, agreement, and grammatical structure can differ greatly from English. Concatenating fragments, or composing a sentence by positioning elements with CSS or HTML layout, makes it impossible for translators to produce natural-sounding results. | ||
|
|
||
| If there's no string you can reuse, allocate an available key in the appropriate translation dictionary and add the default string, e.g. | ||
|
|
||
| ```json | ||
| ..., | ||
| "section/newkey": "new default string for this key", | ||
| ... | ||
| ``` | ||
|
|
||
| and then set the text (or HTML) of your HTML element using i18n helper method. So given an HTML fragment like: | ||
| ```html | ||
| <label id="new-element-id">[untranslated text would have appeared here before]</label> | ||
| ``` | ||
| we could set its text using: | ||
| ```javascript | ||
| $('#new-html-element-id').text($.i18n('section/newkey')); | ||
| ``` | ||
| or, if you need to embed HTML tags: | ||
| ```javascript | ||
| $('#new-html-element-id').html($.i18n('section/newkey')); | ||
| ``` | ||
|
|
||
| HTML should be avoided as it can enable [cross-scripting attacks](https://owasp.org/www-community/attacks/xss/). | ||
|
|
||
| ### Adding a new language {#adding-a-new-language} | ||
|
|
||
| The language dictionaries are stored in the `langs` subdirectory for the module e.g. | ||
|
|
||
| * https://github.com/OpenRefine/OpenRefine/tree/master/main/webapp/modules/core/langs for the main interface | ||
| * https://github.com/OpenRefine/OpenRefine/tree/master/extensions/database/module/langs for database via JDBC | ||
| * https://github.com/OpenRefine/OpenRefine/tree/master/extensions/wikibase/module/langs for the Wikibase extension | ||
|
|
||
| To add support for a new language, the easiest way is to do it directly in Weblate. To do it manually, copy `translation-en.json` to `translation-<locale>.json` and have your translator translate all the value strings (ie right hand side). | ||
|
|
||
| Once the translation file is in place, register the language in the dropdown menu in `/OpenRefine/main/webapp/modules/core/scripts/index/lang-settings-ui.html`. The entry should look like: | ||
| ```html | ||
| <option value="<locale>">[Language Label]</option> | ||
| ``` | ||
|
|
||
| By default, the system tries to load the language file corresponding to the currently in-use browser language. The "Language Settings" menu item on the index page allows users to override this setting. | ||
|
|
||
| ## Server-side localisation {#server-side-localisation} | ||
|
|
||
| Certain areas of the back-end can also be localized, also via Weblate. | ||
| The translated strings are stored in `.properties` file, from which Java classes are generated at compilation time. | ||
| For instance, operation descriptions are stored under [`main/resources/com/google/refine/operations`](https://github.com/OpenRefine/OpenRefine/tree/master/main/resources/com/google/refine/operations/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we recommend to open the bug on the main Github bug tracker (https://github.com/OpenRefine/OpenRefine/issues/new?template=bug_report.md ) and then the team triage the right repo? This would be the case if the missing translation is on an extension.