Merge branch 'issue7461-localize-remaining-labels' of github.com:diegobenetti/bigbluebutton into test-loc
This commit is contained in:
commit
420bb9b3f8
@ -231,7 +231,13 @@ class Poll extends Component {
|
||||
|
||||
renderActivePollOptions() {
|
||||
const {
|
||||
intl, publishPoll, stopPoll, currentUser, currentPoll, getUser,
|
||||
intl,
|
||||
publishPoll,
|
||||
stopPoll,
|
||||
currentUser,
|
||||
currentPoll,
|
||||
getUser,
|
||||
pollAnswerIds,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -246,6 +252,7 @@ class Poll extends Component {
|
||||
currentUser,
|
||||
getUser,
|
||||
currentPoll,
|
||||
pollAnswerIds,
|
||||
}}
|
||||
handleBackClick={this.handleBackClick}
|
||||
/>
|
||||
|
@ -33,5 +33,6 @@ export default withTracker(() => {
|
||||
currentPoll: Service.currentPoll(),
|
||||
getUser: Service.getUser,
|
||||
resetPollPanel: Session.get('resetPollPanel') || false,
|
||||
pollAnswerIds: Service.pollAnswerIds,
|
||||
};
|
||||
})(PollContainer);
|
||||
|
@ -43,7 +43,9 @@ const getResponseString = (obj) => {
|
||||
|
||||
class LiveResult extends Component {
|
||||
static getDerivedStateFromProps(nextProps) {
|
||||
const { currentPoll, getUser } = nextProps;
|
||||
const {
|
||||
currentPoll, getUser, intl, pollAnswerIds,
|
||||
} = nextProps;
|
||||
|
||||
if (!currentPoll) return null;
|
||||
|
||||
@ -71,19 +73,29 @@ class LiveResult extends Component {
|
||||
};
|
||||
})
|
||||
.sort(Service.sortUsers)
|
||||
.reduce((acc, user) => [
|
||||
...acc,
|
||||
(
|
||||
<tr key={_.uniqueId('stats-')}>
|
||||
<td className={styles.resultLeft}>{user.name}</td>
|
||||
<td className={styles.resultRight}>{user.answer}</td>
|
||||
</tr>
|
||||
),
|
||||
], []);
|
||||
.reduce((acc, user) => {
|
||||
const formattedMessageIndex = user.answer.toLowerCase();
|
||||
return ([
|
||||
...acc,
|
||||
(
|
||||
<tr key={_.uniqueId('stats-')}>
|
||||
<td className={styles.resultLeft}>{user.name}</td>
|
||||
<td className={styles.resultRight}>
|
||||
{
|
||||
pollAnswerIds[formattedMessageIndex]
|
||||
? intl.formatMessage(pollAnswerIds[formattedMessageIndex])
|
||||
: user.answer
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
),
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const pollStats = [];
|
||||
|
||||
answers.map((obj) => {
|
||||
const formattedMessageIndex = obj.key.toLowerCase();
|
||||
const pct = Math.round(obj.numVotes / numRespondents * 100);
|
||||
const pctFotmatted = `${Number.isNaN(pct) ? 0 : pct}%`;
|
||||
|
||||
@ -94,7 +106,11 @@ class LiveResult extends Component {
|
||||
return pollStats.push(
|
||||
<div className={styles.main} key={_.uniqueId('stats-')}>
|
||||
<div className={styles.left}>
|
||||
{obj.key}
|
||||
{
|
||||
pollAnswerIds[formattedMessageIndex]
|
||||
? intl.formatMessage(pollAnswerIds[formattedMessageIndex])
|
||||
: obj.key
|
||||
}
|
||||
</div>
|
||||
<div className={styles.center}>
|
||||
<div className={styles.barShade} style={calculatedWidth} />
|
||||
|
@ -11,6 +11,45 @@ import Polls from '/imports/api/polls';
|
||||
// 'A-5' = A,B,C,D,E
|
||||
const pollTypes = ['YN', 'TF', 'A-2', 'A-3', 'A-4', 'A-5', 'custom'];
|
||||
|
||||
const pollAnswerIds = {
|
||||
true: {
|
||||
id: 'app.poll.answer.true',
|
||||
description: 'label for poll answer True',
|
||||
},
|
||||
false: {
|
||||
id: 'app.poll.answer.false',
|
||||
description: 'label for poll answer False',
|
||||
},
|
||||
yes: {
|
||||
id: 'app.poll.answer.yes',
|
||||
description: 'label for poll answer Yes',
|
||||
},
|
||||
no: {
|
||||
id: 'app.poll.answer.no',
|
||||
description: 'label for poll answer No',
|
||||
},
|
||||
a: {
|
||||
id: 'app.poll.answer.a',
|
||||
description: 'label for poll answer A',
|
||||
},
|
||||
b: {
|
||||
id: 'app.poll.answer.b',
|
||||
description: 'label for poll answer B',
|
||||
},
|
||||
c: {
|
||||
id: 'app.poll.answer.c',
|
||||
description: 'label for poll answer C',
|
||||
},
|
||||
d: {
|
||||
id: 'app.poll.answer.d',
|
||||
description: 'label for poll answer D',
|
||||
},
|
||||
e: {
|
||||
id: 'app.poll.answer.e',
|
||||
description: 'label for poll answer E',
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
currentUser: () => Users.findOne({ userId: Auth.userID }),
|
||||
pollTypes,
|
||||
@ -18,4 +57,5 @@ export default {
|
||||
publishPoll: () => makeCall('publishPoll'),
|
||||
currentPoll: () => Polls.findOne({ meetingId: Auth.meetingID }),
|
||||
getUser: userId => Users.findOne({ userId }),
|
||||
pollAnswerIds,
|
||||
};
|
||||
|
@ -36,7 +36,9 @@ class Polling extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, poll, handleVote } = this.props;
|
||||
const {
|
||||
intl, poll, handleVote, pollAnswerIds,
|
||||
} = this.props;
|
||||
const { stackOptions, answers } = poll;
|
||||
const pollAnswerStyles = {
|
||||
[styles.pollingAnswers]: true,
|
||||
@ -57,40 +59,48 @@ class Polling extends Component {
|
||||
{intl.formatMessage(intlMessages.pollingTitleLabel)}
|
||||
</div>
|
||||
<div className={cx(pollAnswerStyles)}>
|
||||
{poll.answers.map(pollAnswer => (
|
||||
<div
|
||||
key={pollAnswer.id}
|
||||
className={styles.pollButtonWrapper}
|
||||
>
|
||||
<Tooltip
|
||||
{poll.answers.map((pollAnswer) => {
|
||||
const formattedMessageIndex = pollAnswer.key.toLowerCase();
|
||||
let label = pollAnswer.key;
|
||||
if (pollAnswerIds[formattedMessageIndex]) {
|
||||
label = intl.formatMessage(pollAnswerIds[formattedMessageIndex]);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={pollAnswer.id}
|
||||
title={pollAnswer.key}
|
||||
className={styles.pollButtonWrapper}
|
||||
>
|
||||
<Button
|
||||
className={styles.pollingButton}
|
||||
color="primary"
|
||||
size="md"
|
||||
label={pollAnswer.key}
|
||||
key={pollAnswer.key}
|
||||
onClick={() => handleVote(poll.pollId, pollAnswer)}
|
||||
aria-labelledby={`pollAnswerLabel${pollAnswer.key}`}
|
||||
aria-describedby={`pollAnswerDesc${pollAnswer.key}`}
|
||||
/>
|
||||
</Tooltip>
|
||||
<div
|
||||
className={styles.hidden}
|
||||
id={`pollAnswerLabel${pollAnswer.key}`}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.pollAnswerLabel, { 0: pollAnswer.key })}
|
||||
<Tooltip
|
||||
key={pollAnswer.id}
|
||||
title={label}
|
||||
>
|
||||
<Button
|
||||
className={styles.pollingButton}
|
||||
color="primary"
|
||||
size="md"
|
||||
label={label}
|
||||
key={pollAnswer.key}
|
||||
onClick={() => handleVote(poll.pollId, pollAnswer)}
|
||||
aria-labelledby={`pollAnswerLabel${pollAnswer.key}`}
|
||||
aria-describedby={`pollAnswerDesc${pollAnswer.key}`}
|
||||
/>
|
||||
</Tooltip>
|
||||
<div
|
||||
className={styles.hidden}
|
||||
id={`pollAnswerLabel${pollAnswer.key}`}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.pollAnswerLabel, { 0: label })}
|
||||
</div>
|
||||
<div
|
||||
className={styles.hidden}
|
||||
id={`pollAnswerDesc${pollAnswer.key}`}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.pollAnswerDesc, { 0: label })}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles.hidden}
|
||||
id={`pollAnswerDesc${pollAnswer.key}`}
|
||||
>
|
||||
{intl.formatMessage(intlMessages.pollAnswerDesc, { 0: pollAnswer.key })}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
|
@ -4,6 +4,7 @@ import { withTracker } from 'meteor/react-meteor-data';
|
||||
import Users from '/imports/api/users';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import PollingService from './service';
|
||||
import Service from '/imports/ui/components/poll/service';
|
||||
import PollingComponent from './component';
|
||||
|
||||
const propTypes = {
|
||||
@ -23,6 +24,11 @@ const PollingContainer = ({ pollExists, ...props }) => {
|
||||
PollingContainer.propTypes = propTypes;
|
||||
|
||||
export default withTracker(() => {
|
||||
const data = PollingService.mapPolls();
|
||||
return data;
|
||||
const { pollExists, handleVote, poll } = PollingService.mapPolls();
|
||||
return ({
|
||||
pollExists,
|
||||
handleVote,
|
||||
poll,
|
||||
pollAnswerIds: Service.pollAnswerIds,
|
||||
});
|
||||
})(PollingContainer);
|
||||
|
@ -249,7 +249,6 @@ class Settings extends Component {
|
||||
const {
|
||||
intl,
|
||||
mountModal,
|
||||
notify,
|
||||
} = this.props;
|
||||
const {
|
||||
current,
|
||||
@ -260,16 +259,11 @@ class Settings extends Component {
|
||||
title={intl.formatMessage(intlMessages.SettingsLabel)}
|
||||
confirm={{
|
||||
callback: () => {
|
||||
this.updateSettings(current);
|
||||
this.updateSettings(current, intl.formatMessage(intlMessages.savedAlertLabel));
|
||||
/* We need to use mountModal(null) here to prevent submenu state updates,
|
||||
* from re-opening the modal.
|
||||
*/
|
||||
mountModal(null);
|
||||
notify(
|
||||
intl.formatMessage(intlMessages.savedAlertLabel),
|
||||
'info',
|
||||
'settings',
|
||||
);
|
||||
},
|
||||
label: intl.formatMessage(intlMessages.SaveLabel),
|
||||
description: intl.formatMessage(intlMessages.SaveLabelDesc),
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { withTracker } from 'meteor/react-meteor-data';
|
||||
import SettingsService from '/imports/ui/services/settings';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
import Settings from './component';
|
||||
|
||||
import {
|
||||
@ -25,5 +24,4 @@ export default withTracker(() => ({
|
||||
locales: getClosedCaptionLocales(),
|
||||
availableLocales: getAvailableLocales(),
|
||||
isModerator: getUserRoles() === 'MODERATOR',
|
||||
notify,
|
||||
}))(SettingsContainer);
|
||||
|
@ -3,6 +3,7 @@ import Captions from '/imports/api/captions';
|
||||
import Auth from '/imports/ui/services/auth';
|
||||
import _ from 'lodash';
|
||||
import Settings from '/imports/ui/services/settings';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
|
||||
const getClosedCaptionLocales = () => {
|
||||
// list of unique locales in the Captions Collection
|
||||
@ -22,9 +23,20 @@ const getUserRoles = () => {
|
||||
return user.role;
|
||||
};
|
||||
|
||||
const updateSettings = (obj) => {
|
||||
const updateSettings = (obj, msg) => {
|
||||
Object.keys(obj).forEach(k => (Settings[k] = obj[k]));
|
||||
Settings.save();
|
||||
|
||||
if (msg) {
|
||||
// prevents React state update on unmounted component
|
||||
setTimeout(() => {
|
||||
notify(
|
||||
msg,
|
||||
'info',
|
||||
'settings',
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
const getAvailableLocales = () => fetch('/html5client/locales').then(locales => locales.json());
|
||||
|
@ -37,7 +37,7 @@ class UserPolls extends PureComponent {
|
||||
<div className={styles.messages}>
|
||||
{
|
||||
<h2 className={styles.smallTitle}>
|
||||
{'Polling'}
|
||||
{intl.formatMessage(intlMessages.pollLabel)}
|
||||
</h2>
|
||||
}
|
||||
<div className={styles.scrollableList}>
|
||||
|
@ -1,15 +1,9 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { notify } from '/imports/ui/services/notification';
|
||||
import Service from '/imports/ui/components/poll/service';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
const intlMessages = defineMessages({
|
||||
pollPublishedLabel: {
|
||||
id: 'app.whiteboard.annotations.poll',
|
||||
description: 'message displayed when a poll is published',
|
||||
},
|
||||
});
|
||||
|
||||
class PollDrawComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -60,18 +54,12 @@ class PollDrawComponent extends Component {
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { intl } = this.props;
|
||||
notify(
|
||||
intl.formatMessage(intlMessages.pollPublishedLabel),
|
||||
'info',
|
||||
'polling',
|
||||
);
|
||||
// in this part we retrieve the props and perform initial calculations for the state
|
||||
// calculating only the parts which have to be done just once and don't require
|
||||
// rendering / rerendering the text objects
|
||||
|
||||
const { points, result } = this.props.annotation;
|
||||
const { slideWidth, slideHeight } = this.props;
|
||||
const { slideWidth, slideHeight, intl } = this.props;
|
||||
|
||||
// x1 and y1 - coordinates of the top left corner of the annotation
|
||||
// initial width and height are the width and height of the annotation
|
||||
@ -135,6 +123,11 @@ class PollDrawComponent extends Component {
|
||||
const maxLineHeight = (innerHeight * 0.75) / textArray.length;
|
||||
|
||||
const lineToMeasure = textArray[0];
|
||||
const pollAnswerIds = Service.pollAnswerIds;
|
||||
const messageIndex = lineToMeasure[0].toLowerCase();
|
||||
if (pollAnswerIds[messageIndex]) {
|
||||
lineToMeasure[0] = intl.formatMessage(pollAnswerIds[messageIndex]);
|
||||
}
|
||||
|
||||
// saving all the initial calculations in the state
|
||||
this.setState({
|
||||
@ -190,9 +183,9 @@ class PollDrawComponent extends Component {
|
||||
|
||||
// first check if we can still increase the font-size
|
||||
if (this.state.fontSizeDirection === 1) {
|
||||
if (keySizes.width < maxLineWidth && keySizes.height < maxLineHeight &&
|
||||
voteSizes.width < maxLineWidth && voteSizes.height < maxLineHeight &&
|
||||
percSizes.width < maxLineWidth && percSizes.height < maxLineHeight) {
|
||||
if (keySizes.width < maxLineWidth && keySizes.height < maxLineHeight
|
||||
&& voteSizes.width < maxLineWidth && voteSizes.height < maxLineHeight
|
||||
&& percSizes.width < maxLineWidth && percSizes.height < maxLineHeight) {
|
||||
return this.setState({
|
||||
calcFontSize: this.state.calcFontSize + 1,
|
||||
});
|
||||
@ -203,11 +196,11 @@ class PollDrawComponent extends Component {
|
||||
fontSizeDirection: -1,
|
||||
calcFontSize: this.state.calcFontSize - 1,
|
||||
});
|
||||
} else if (this.state.fontSizeDirection === -1) {
|
||||
} if (this.state.fontSizeDirection === -1) {
|
||||
// check if the font-size is still bigger than allowed
|
||||
if (keySizes.width > maxLineWidth || keySizes.height > maxLineHeight ||
|
||||
voteSizes.width > maxLineWidth || voteSizes.height > maxLineHeight ||
|
||||
percSizes.width > maxLineWidth || percSizes.height > maxLineHeight) {
|
||||
if (keySizes.width > maxLineWidth || keySizes.height > maxLineHeight
|
||||
|| voteSizes.width > maxLineWidth || voteSizes.height > maxLineHeight
|
||||
|| percSizes.width > maxLineWidth || percSizes.height > maxLineHeight) {
|
||||
return this.setState({
|
||||
calcFontSize: this.state.calcFontSize - 1,
|
||||
});
|
||||
@ -289,7 +282,9 @@ class PollDrawComponent extends Component {
|
||||
thickness,
|
||||
} = this.state;
|
||||
|
||||
const { annotation } = this.props;
|
||||
const { annotation, intl } = this.props;
|
||||
|
||||
const pollAnswerIds = Service.pollAnswerIds;
|
||||
|
||||
//* ********************************************************************************************
|
||||
//* *****************************************MAGIC NUMBER***************************************
|
||||
@ -323,8 +318,8 @@ class PollDrawComponent extends Component {
|
||||
|
||||
// Initial coordinates of the percentage column
|
||||
let yRight = ((innerRect.y + verticalPadding) + (barHeight / 2)) - magicNumber;
|
||||
const xRight = ((((innerRect.x + (horizontalPadding * 3)) +
|
||||
maxLeftWidth) + maxRightWidth) + maxBarWidth + 1);
|
||||
const xRight = ((((innerRect.x + (horizontalPadding * 3))
|
||||
+ maxLeftWidth) + maxRightWidth) + maxBarWidth + 1);
|
||||
|
||||
let yNumVotes = (innerRect.y + verticalPadding) - magicNumber;
|
||||
const extendedTextArray = [];
|
||||
@ -336,6 +331,12 @@ class PollDrawComponent extends Component {
|
||||
barWidth = (annotation.result[i].numVotes / maxNumVotes) * maxBarWidth;
|
||||
}
|
||||
|
||||
let label = textArray[i][0];
|
||||
const formattedMessageIndex = label.toLowerCase();
|
||||
if (pollAnswerIds[formattedMessageIndex]) {
|
||||
label = intl.formatMessage(pollAnswerIds[formattedMessageIndex]);
|
||||
}
|
||||
|
||||
// coordinates and color of the text inside the line bar
|
||||
// xNumVotesDefault and xNumVotesMovedRight are 2 different x coordinates for the text
|
||||
// since if the line bar is too small then we place the number to the right of the bar
|
||||
@ -352,11 +353,10 @@ class PollDrawComponent extends Component {
|
||||
color = 'white';
|
||||
}
|
||||
|
||||
extendedTextArray[i] =
|
||||
{
|
||||
extendedTextArray[i] = {
|
||||
key: `${annotation.id}_${textArray[i][3]}`,
|
||||
keyColumn: {
|
||||
keyString: textArray[i][0],
|
||||
keyString: label,
|
||||
xLeft,
|
||||
yLeft,
|
||||
},
|
||||
@ -412,19 +412,19 @@ class PollDrawComponent extends Component {
|
||||
fontSize={calcFontSize}
|
||||
textAnchor="start"
|
||||
>
|
||||
{extendedTextArray.map(line =>
|
||||
(<tspan
|
||||
{extendedTextArray.map(line => (
|
||||
<tspan
|
||||
x={line.keyColumn.xLeft}
|
||||
y={line.keyColumn.yLeft}
|
||||
dy={maxLineHeight / 2}
|
||||
key={`${line.key}_key`}
|
||||
>
|
||||
{line.keyColumn.keyString}
|
||||
</tspan>),
|
||||
)}
|
||||
</tspan>
|
||||
))}
|
||||
</text>
|
||||
{extendedTextArray.map(line =>
|
||||
(<rect
|
||||
{extendedTextArray.map(line => (
|
||||
<rect
|
||||
key={`${line.key}_bar`}
|
||||
x={line.barColumn.xBar}
|
||||
y={line.barColumn.yBar}
|
||||
@ -433,8 +433,8 @@ class PollDrawComponent extends Component {
|
||||
stroke="#333333"
|
||||
fill="#333333"
|
||||
strokeWidth={thickness - 1}
|
||||
/>),
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
<text
|
||||
x={innerRect.x}
|
||||
y={innerRect.y}
|
||||
@ -443,16 +443,16 @@ class PollDrawComponent extends Component {
|
||||
fontSize={calcFontSize}
|
||||
textAnchor="end"
|
||||
>
|
||||
{extendedTextArray.map(line =>
|
||||
(<tspan
|
||||
{extendedTextArray.map(line => (
|
||||
<tspan
|
||||
x={line.percentColumn.xRight}
|
||||
y={line.percentColumn.yRight}
|
||||
dy={maxLineHeight / 2}
|
||||
key={`${line.key}_percent`}
|
||||
>
|
||||
{line.percentColumn.percentString}
|
||||
</tspan>),
|
||||
)}
|
||||
</tspan>
|
||||
))}
|
||||
</text>
|
||||
<text
|
||||
x={innerRect.x}
|
||||
@ -461,8 +461,8 @@ class PollDrawComponent extends Component {
|
||||
fontFamily="Arial"
|
||||
fontSize={calcFontSize}
|
||||
>
|
||||
{extendedTextArray.map(line =>
|
||||
(<tspan
|
||||
{extendedTextArray.map(line => (
|
||||
<tspan
|
||||
x={line.barColumn.xNumVotes + (line.barColumn.barWidth / 2)}
|
||||
y={line.barColumn.yNumVotes + (line.barColumn.barHeight / 2)}
|
||||
dy={maxLineHeight / 2}
|
||||
@ -470,8 +470,8 @@ class PollDrawComponent extends Component {
|
||||
fill={line.barColumn.color}
|
||||
>
|
||||
{line.barColumn.numVotes}
|
||||
</tspan>),
|
||||
)}
|
||||
</tspan>
|
||||
))}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
@ -522,9 +522,7 @@ class PollDrawComponent extends Component {
|
||||
}
|
||||
return (
|
||||
<g>
|
||||
{this.state.textArray.map(line =>
|
||||
this.renderLine(line),
|
||||
)
|
||||
{this.state.textArray.map(line => this.renderLine(line))
|
||||
}
|
||||
<text
|
||||
fontFamily="Arial"
|
||||
@ -542,10 +540,9 @@ class PollDrawComponent extends Component {
|
||||
render() {
|
||||
return (
|
||||
<g>
|
||||
{this.state.prepareToDisplay ?
|
||||
this.renderTestStrings()
|
||||
:
|
||||
this.renderPoll()
|
||||
{this.state.prepareToDisplay
|
||||
? this.renderTestStrings()
|
||||
: this.renderPoll()
|
||||
}
|
||||
</g>
|
||||
);
|
||||
|
@ -162,6 +162,15 @@
|
||||
"app.poll.a3": "A / B / C",
|
||||
"app.poll.a4": "A / B / C / D",
|
||||
"app.poll.a5": "A / B / C / D / E",
|
||||
"app.poll.answer.true": "True",
|
||||
"app.poll.answer.false": "False",
|
||||
"app.poll.answer.yes": "Yes",
|
||||
"app.poll.answer.no": "No",
|
||||
"app.poll.answer.a": "A",
|
||||
"app.poll.answer.b": "B",
|
||||
"app.poll.answer.c": "C",
|
||||
"app.poll.answer.d": "D",
|
||||
"app.poll.answer.e": "E",
|
||||
"app.poll.liveResult.usersTitle": "Users",
|
||||
"app.poll.liveResult.responsesTitle": "Response",
|
||||
"app.polling.pollingTitle": "Polling options",
|
||||
|
Loading…
Reference in New Issue
Block a user