mirror of
https://github.com/SchildiChat/element-web.git
synced 2024-10-01 01:26:12 -04:00
Merge pull request #5613 from pafcu/simplify-translation
Refactor translations
This commit is contained in:
commit
cb235a29fa
@ -36,9 +36,13 @@ function getColorName(hex) {
|
|||||||
## Adding variables inside a string.
|
## Adding variables inside a string.
|
||||||
|
|
||||||
1. Extend your ``_t()`` call. Instead of ``_t(STRING)`` use ``_t(STRING, {})``
|
1. Extend your ``_t()`` call. Instead of ``_t(STRING)`` use ``_t(STRING, {})``
|
||||||
2. Decide how to name it. Please think about if the person who has to translate it can understand what it does.
|
1. Decide how to name it. Please think about if the person who has to translate it can understand what it does. E.g. using the name 'recipient' is bad, because a translator does not know if it is the name of a person, an email address, a user ID, etc. Rather use e.g. recipientEmailAddress.
|
||||||
3. Add it to the array in ``_t`` for example ``_t(STRING, {variable: this.variable})``
|
1. Add it to the array in ``_t`` for example ``_t(STRING, {variable: this.variable})``
|
||||||
4. Add the variable inside the string. The syntax for variables is ``%(variable)s``. Please note the s at the end. The name of the variable has to match the previous used name.
|
1. Add the variable inside the string. The syntax for variables is ``%(variable)s``. Please note the _s_ at the end. The name of the variable has to match the previous used name.
|
||||||
|
|
||||||
|
- You can use the special ``count`` variable to choose between multiple versions of the same string, in order to get the correct pluralization. E.g. ``_t('You have %(count)s new messages', { count: 2 })`` would show 'You have 2 new messages', while ``_t('You have %(count)s new messages', { count: 1 })`` would show 'You have one new message' (assuming a singular version of the string has been added to the translation file. See above). Passing in ``count`` is much prefered over having an if-statement choose the correct string to use, because some languages have much more complicated plural rules than english (e.g. they might need a completely different form if there are three things rather than two).
|
||||||
|
- If you want to translate text that includes e.g. hyperlinks or other HTML you have to also use tag substitution, e.g. ``_t('<a>Click here!</a>', {}, { 'a': (sub) => <a>{sub}</a> })``. If you don't do the tag substitution you will end up showing literally '<a>' rather than making a hyperlink.
|
||||||
|
- You can also use React components with normal variable substitution if you want to insert HTML markup, e.g. ``_t('Your email address is %(emailAddress)s', { emailAddress: <i>{userEmailAddress}</i> })``.
|
||||||
|
|
||||||
## Things to know/Style Guides
|
## Things to know/Style Guides
|
||||||
|
|
||||||
@ -47,3 +51,5 @@ function getColorName(hex) {
|
|||||||
- If a string is presented in the UI with punctuation like a full stop, include this in the translation strings, since punctuation varies between languages too.
|
- If a string is presented in the UI with punctuation like a full stop, include this in the translation strings, since punctuation varies between languages too.
|
||||||
- Avoid "translation in parts", i.e. concatenating translated strings or using translated strings in variable substitutions. Context is important for translations, and translating partial strings this way is simply not always possible.
|
- Avoid "translation in parts", i.e. concatenating translated strings or using translated strings in variable substitutions. Context is important for translations, and translating partial strings this way is simply not always possible.
|
||||||
- Concatenating strings often also introduces an implicit assumption about word order (e.g. that the subject of the sentence comes first), which is incorrect for many languages.
|
- Concatenating strings often also introduces an implicit assumption about word order (e.g. that the subject of the sentence comes first), which is incorrect for many languages.
|
||||||
|
- Translation 'smell test': If you have a string that does not begin with a capital letter (is not the start of a sentence) or it ends with e.g. ':' or a preposition (e.g. 'to') you should recheck that you are not trying to translate a partial sentence.
|
||||||
|
- If you have multiple strings, that are almost identical, except some part (e.g. a word or two) it is still better to translate the full sentence multiple times. It may seem like inefficient repetion, but unlike programming where you try to minimize repetition, translation is much faster if you have many, full, clear, sentences to work with, rather than fewer, but incomplete sentence fragments.
|
||||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var React = require('react');
|
var React = require('react');
|
||||||
import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
|
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
displayName: 'CompatibilityPage',
|
displayName: 'CompatibilityPage',
|
||||||
@ -40,30 +40,24 @@ module.exports = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div className="mx_CompatibilityPage">
|
<div className="mx_CompatibilityPage">
|
||||||
<div className="mx_CompatibilityPage_box">
|
<div className="mx_CompatibilityPage_box">
|
||||||
<p>{ _tJsx("Sorry, your browser is <b>not</b> able to run Riot.", /<b>(.*?)<\/b>/, (sub) => <b>{sub}</b>) } </p>
|
<p>{ _t("Sorry, your browser is <b>not</b> able to run Riot.", {}, { 'b': (sub) => <b>{sub}</b> }) } </p>
|
||||||
<p>
|
<p>
|
||||||
{ _t("Riot uses many advanced browser features, some of which are not available or experimental in your current browser.") }
|
{ _t("Riot uses many advanced browser features, some of which are not available or experimental in your current browser.") }
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{ _tJsx('Please install <a href="https://www.google.com/chrome">Chrome</a> or <a href="https://getfirefox.com">Firefox</a> for the best experience.',
|
{ _t('Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.',
|
||||||
[
|
{},
|
||||||
/<a href="https:\/\/www.google.com\/chrome">(.*?)<\/a>/,
|
{
|
||||||
/<a href="https:\/\/getfirefox.com">(.*?)<\/a>/,
|
'chromeLink': (sub) => <a href="https://www.google.com/chrome">{sub}</a>,
|
||||||
],
|
'firefoxLink': (sub) => <a href="https://getfirefox.com">{sub}</a>,
|
||||||
[
|
},
|
||||||
(sub) => <a href="https://www.google.com/chrome">{sub}</a>,
|
|
||||||
(sub) => <a href="https://getfirefox.com">{sub}</a>,
|
|
||||||
]
|
|
||||||
)}
|
)}
|
||||||
{ _tJsx('<a href="http://apple.com/safari">Safari</a> and <a href="http://opera.com">Opera</a> work too.',
|
{ _t('<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.',
|
||||||
[
|
{},
|
||||||
/<a href="http:\/\/apple\.com\/safari">(.*?)<\/a>/,
|
{
|
||||||
/<a href="http:\/\/opera\.com">(.*?)<\/a>/,
|
'safariLink': (sub) => <a href="http://apple.com/safari">{sub}</a>,
|
||||||
],
|
'operaLink': (sub) => <a href="http://opera.com">{sub}</a>,
|
||||||
[
|
},
|
||||||
(sub) => <a href="http://apple.com/safari">{sub}</a>,
|
|
||||||
(sub) => <a href="http://opera.com">{sub}</a>,
|
|
||||||
]
|
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -20,7 +20,7 @@ import React from 'react';
|
|||||||
import sdk from 'matrix-react-sdk';
|
import sdk from 'matrix-react-sdk';
|
||||||
import Modal from 'matrix-react-sdk/lib/Modal';
|
import Modal from 'matrix-react-sdk/lib/Modal';
|
||||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||||
import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
|
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||||
|
|
||||||
export default React.createClass({
|
export default React.createClass({
|
||||||
onUpdateClicked: function() {
|
onUpdateClicked: function() {
|
||||||
@ -49,10 +49,10 @@ export default React.createClass({
|
|||||||
alt="Warning"
|
alt="Warning"
|
||||||
/>
|
/>
|
||||||
<div className="mx_MatrixToolbar_content">
|
<div className="mx_MatrixToolbar_content">
|
||||||
{ _tJsx(
|
{ _t(
|
||||||
"To return to your account in future you need to <u>set a password</u>",
|
"To return to your account in future you need to <u>set a password</u>",
|
||||||
/<u>(.*?)<\/u>/,
|
{},
|
||||||
(sub) => { return <u>{ sub }</u>; },
|
{ 'u': (sub) => <u>{ sub }</u> },
|
||||||
) }
|
) }
|
||||||
</div>
|
</div>
|
||||||
<button className="mx_MatrixToolbar_action">
|
<button className="mx_MatrixToolbar_action">
|
||||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
import sdk from 'matrix-react-sdk';
|
import sdk from 'matrix-react-sdk';
|
||||||
import { _t, _tJsx } from 'matrix-react-sdk/lib/languageHandler';
|
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||||
import UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
|
import UserSettingsStore from 'matrix-react-sdk/lib/UserSettingsStore';
|
||||||
import SettingsStore, {SettingLevel} from "matrix-react-sdk/lib/settings/SettingsStore";
|
import SettingsStore, {SettingLevel} from "matrix-react-sdk/lib/settings/SettingsStore";
|
||||||
@ -564,10 +564,11 @@ module.exports = React.createClass({
|
|||||||
"vectorRuleId": "_keywords",
|
"vectorRuleId": "_keywords",
|
||||||
"description" : (
|
"description" : (
|
||||||
<span>
|
<span>
|
||||||
{ _tJsx('Messages containing <span>keywords</span>',
|
{ _t('Messages containing <span>keywords</span>',
|
||||||
/<span>(.*?)<\/span>/,
|
{},
|
||||||
(sub) =>
|
{ 'span': (sub) =>
|
||||||
<span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>
|
<span className="mx_UserNotifSettings_keywords" onClick={ self.onKeywordsClicked }>{sub}</span>
|
||||||
|
},
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
|
@ -72,7 +72,6 @@
|
|||||||
"Away": "Away",
|
"Away": "Away",
|
||||||
"A new version of Riot is available.": "A new version of Riot is available.",
|
"A new version of Riot is available.": "A new version of Riot is available.",
|
||||||
"To return to your account in future you need to <u>set a password</u>": "To return to your account in future you need to <u>set a password</u>",
|
"To return to your account in future you need to <u>set a password</u>": "To return to your account in future you need to <u>set a password</u>",
|
||||||
"Toolbox": "Toolbox",
|
|
||||||
"Set Password": "Set Password",
|
"Set Password": "Set Password",
|
||||||
"Error encountered (%(errorDetail)s).": "Error encountered (%(errorDetail)s).",
|
"Error encountered (%(errorDetail)s).": "Error encountered (%(errorDetail)s).",
|
||||||
"Checking for an update...": "Checking for an update...",
|
"Checking for an update...": "Checking for an update...",
|
||||||
@ -100,18 +99,19 @@
|
|||||||
"Unavailable": "Unavailable",
|
"Unavailable": "Unavailable",
|
||||||
"Changelog": "Changelog",
|
"Changelog": "Changelog",
|
||||||
"Back": "Back",
|
"Back": "Back",
|
||||||
|
"Send Custom Event": "Send Custom Event",
|
||||||
"You must specify an event type!": "You must specify an event type!",
|
"You must specify an event type!": "You must specify an event type!",
|
||||||
"Event sent!": "Event sent!",
|
"Event sent!": "Event sent!",
|
||||||
"Failed to send custom event.": "Failed to send custom event.",
|
"Failed to send custom event.": "Failed to send custom event.",
|
||||||
"Event Type": "Event Type",
|
"Event Type": "Event Type",
|
||||||
"Event Content": "Event Content",
|
|
||||||
"State Key": "State Key",
|
"State Key": "State Key",
|
||||||
"Edit": "Edit",
|
"Event Content": "Event Content",
|
||||||
"Filter results": "Filter results",
|
|
||||||
"Send Custom Event": "Send Custom Event",
|
|
||||||
"Send Account Data": "Send Account Data",
|
"Send Account Data": "Send Account Data",
|
||||||
"Explore Account Data": "Explore Account Data",
|
"Filter results": "Filter results",
|
||||||
"Explore Room State": "Explore Room State",
|
"Explore Room State": "Explore Room State",
|
||||||
|
"Edit": "Edit",
|
||||||
|
"Explore Account Data": "Explore Account Data",
|
||||||
|
"Toolbox": "Toolbox",
|
||||||
"Developer Tools": "Developer Tools",
|
"Developer Tools": "Developer Tools",
|
||||||
"You have successfully set a password!": "You have successfully set a password!",
|
"You have successfully set a password!": "You have successfully set a password!",
|
||||||
"You have successfully set a password and an email address!": "You have successfully set a password and an email address!",
|
"You have successfully set a password and an email address!": "You have successfully set a password and an email address!",
|
||||||
@ -149,8 +149,8 @@
|
|||||||
"Direct Chat": "Direct Chat",
|
"Direct Chat": "Direct Chat",
|
||||||
"Sorry, your browser is <b>not</b> able to run Riot.": "Sorry, your browser is <b>not</b> able to run Riot.",
|
"Sorry, your browser is <b>not</b> able to run Riot.": "Sorry, your browser is <b>not</b> able to run Riot.",
|
||||||
"Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.",
|
"Riot uses many advanced browser features, some of which are not available or experimental in your current browser.": "Riot uses many advanced browser features, some of which are not available or experimental in your current browser.",
|
||||||
"Please install <a href=\"https://www.google.com/chrome\">Chrome</a> or <a href=\"https://getfirefox.com\">Firefox</a> for the best experience.": "Please install <a href=\"https://www.google.com/chrome\">Chrome</a> or <a href=\"https://getfirefox.com\">Firefox</a> for the best experience.",
|
"Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.": "Please install <chromeLink>Chrome</chromeLink> or <firefoxLink>Firefox</firefoxLink> for the best experience.",
|
||||||
"<a href=\"http://apple.com/safari\">Safari</a> and <a href=\"http://opera.com\">Opera</a> work too.": "<a href=\"http://apple.com/safari\">Safari</a> and <a href=\"http://opera.com\">Opera</a> work too.",
|
"<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.": "<safariLink>Safari</safariLink> and <operaLink>Opera</operaLink> work too.",
|
||||||
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
|
"With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!": "With your current browser, the look and feel of the application may be completely incorrect, and some or all features may not function. If you want to try it anyway you can continue, but you are on your own in terms of any issues you may encounter!",
|
||||||
"I understand the risks and wish to continue": "I understand the risks and wish to continue",
|
"I understand the risks and wish to continue": "I understand the risks and wish to continue",
|
||||||
"Couldn't load home page": "Couldn't load home page",
|
"Couldn't load home page": "Couldn't load home page",
|
||||||
|
Loading…
Reference in New Issue
Block a user