From beafd507b8519d45a0c1b2cadba65530e9a7c656 Mon Sep 17 00:00:00 2001
From: Loren Johnson
- We're happy you're here! Please take a moment to explore this page to see what's alive in our group. Introduce yourself by clicking Create to post a Discussion sharing who you are and what brings you to our group. And don't forget to fill out your profile - so likeminded new friends can connect with you!
+ {t("We're happy you're here! Please take a moment to explore this page to see what's alive in our group. Introduce yourself by clicking Create to post a Discussion sharing who you are and what brings you to our group. And don't forget to fill out your profile - so likeminded new friends can connect with you!")}
{t('The {{title}} section is not visible to members of this group. Click the three dots', { title: WIDGETS[name].moderatorTitle || WIDGETS[name].title })} ( The {WIDGETS[name].moderatorTitle || WIDGETS[name].title} section is not visible to members of this group. Click the three dots ( {visibilityString(group.visibility)} - {visibilityDescription(group.visibility)} Add a description, location, suggested topics and more in your group settings {this.props.t('Add a description, location, suggested topics and more in your group settings')} This function exports all member data for this group as a CSV file for import into other software. {t('This function exports all member data for this group as a CSV file for import into other software.')} {status} Note: as a moderator you will always see the exact location displayed {this.props.t('Note: as a moderator you will always see the exact location displayed')} What skills and interests are particularly relevant to this group? {this.props.t('What skills and interests are particularly relevant to this group?')}
- Note: as a moderator you will always see the exact location displayed
-
- What skills and interests are particularly relevant to this group?
- Who is able to see {name}? {this.props.t('Who is able to see {{name}}?', { name })} How can people become members of {name}? {this.props.t('How can people become members of {{name}}?', { name })} When you select a prerequisite group, people must join the selected groups before joining {name}. Only parent groups can be added as prerequisite groups.
+ {this.props.t('When you select a prerequisite group, people must join the selected groups before joining {{name}}. Only parent groups can be added as prerequisite groups.', { name })} {/* TODO: handle this translation */}
Warning: If you select a prerequisite group that has a visibility setting of
What questions are asked when a group requests to join this group? {this.props.t('What questions are asked when a group requests to join this group?')} If you don't want to display the detailed {type} specific data on your group's profile {this.props.t('If you don\'t want to display the detailed {{type}} specific data on your group\'s profile', { type })}
- Who is able to see
-
- Foomunity
-
- ?
-
- How can people become members of
-
- Foomunity
-
- ?
-
- When you select a prerequisite group, people must join the selected groups before joining
-
- Foomunity
-
- . Only parent groups can be added as prerequisite groups.
-
+
@@ -140,14 +117,10 @@ exports[`PrivacySettingsTab renders correctly 1`] = `
/>
- What questions are asked when a group requests to join this group?
- {get('answer', questionAnswers && questionAnswers.find(qa => qa.question.id === q.questionId)) || Not answered} {get('answer', questionAnswers && questionAnswers.find(qa => qa.question.id === q.questionId)) || {t('Not answered')}}
- Set default topics for your group which will be suggested first when
+ {this.props.t(`Set default topics for your group which will be suggested first when
members are creating a new post.
- Every new member will also be subscribed to these topics when they join.
+ Every new member will also be subscribed to these topics when they join.`)}
- Below is a list of every topic that any member of your group has used to date. You can choose to hide
+ {this.props.t(`Below is a list of every topic that any member of your group has used to date. You can choose to hide
topics that you would prefer members of your group don't use, or pin topics to the top of the list
- to make sure people pay attention to posts in those topics.
+ to make sure people pay attention to posts in those topics.`)}
We've sent a 6 digit code to {email}. The code will expire shortly, so please enter it here soon. {t("We've sent a 6 digit code to {{email}}. The code will expire shortly, so please enter it here soon.", { email })}
- This action is reversible, just log back in
+ {this.props.t('This action is reversible, just log back in')}
- This action is NOT reversible
+ This action is NOT reversible {/* TODO: Handle this translation */}
Add your location to see more relevant content, and find people and projects around you. {this.props.t('Add your location to see more relevant content, and find people and projects around you')}.
- Add your location to see more relevant content, and find people and projects around you.
+ .
Almost done setting up your profile! Click the above profile icon to upload a custom profile image. Your profile image will be visible when you post or comment in groups. {this.props.t('Almost done setting up your profile! Click the above profile icon to upload a custom profile image. Your profile image will be visible when you post or comment in groups.')} We're glad you're here, {currentUser.name.split(' ')[0]}. To get started, explore public groups and posts, or create your own group! Find out what's happening around you, and groups you can join {this.props.t('Find out what\'s happening around you, and groups you can join')} View and participate in public discussions, projects, events & more {this.props.t('View and participate in public discussions, projects, events & more')} Gather your collaborators & people who share your interests {this.props.t('Gather your collaborators & people who share your interests')} Share about who you are, your skills & interests {this.props.t('Share about who you are, your skills & interests')}
We're glad you're here,
Tibet
@@ -34,12 +32,8 @@ exports[`WelcomeExplore renders correctly 1`] = `
}
/>
- Find out what's happening around you, and groups you can join
-
- View and participate in public discussions, projects, events & more
-
- Gather your collaborators & people who share your interests
-
- Share about who you are, your skills & interests
- text of the comment. a long one. text of the comment. a long one. text of the comment. a long one. text of the comment. a long one. text of the comment. a long one. text of the comment. a long one. Irrelevant Change We use cookies to help understand whether you are logged in and to understand your preferences and where you are in Hylo. We use a service called Mixpanel to understand how people like you use Hylo. Your identity is anonymized but your behavior is recorded so that we can make improvements to Hylo based on how people are using it. Optimizely helps us to test improvements to Hylo by showing different users different sets of features. Optimizely tracks who has seen what and how successful the feature is in accomplishing it's goal When people on Hylo need help or want to report a bug, they are interacting with a service called intercom. Intercom stores cookies in your browser to keep track of conversations with us, the development team. We store images, icons and application data in your browser to improve performance and load times. {t('We use cookies to help understand whether you are logged in and to understand your preferences and where you are in Hylo.')} {t('We use a service called Mixpanel to understand how people like you use Hylo. Your identity is anonymized but your behavior is recorded so that we can make improvements to Hylo based on how people are using it.')} {t('Optimizely helps us to test improvements to Hylo by showing different users different sets of features. Optimizely tracks who has seen what and how successful the feature is in accomplishing it\'s goal')} {t('When people on Hylo need help or want to report a bug, they are interacting with a service called intercom. Intercom stores cookies in your browser to keep track of conversations with us, the development team.')} {t('We store images, icons and application data in your browser to improve performance and load times.')}
- {message}
+ {message}
{hasLocation && 'New Post at this location: '}What would you like to create?
+ {hasLocation && `${t('New Post at this location')}:`}{t('What would you like to create?')}
{postTypes.map(postType => {
querystringParams.set('newPostType', postType)
@@ -40,8 +42,8 @@ export default function CreateModalChooser ({ location }) {
{settings.title || `Welcome to ${group.name}!`}
+ {settings.title || t('Welcome to {{group.name}}!', { group })}
{settings.richText && (
{settings.title || `Welcome to ${group.name}!`}
+ {settings.title || this.props.t('Welcome to {{group.name}}!', { group })}
+
- {group.moderatorDescriptorPlural || 'Moderators'}
+ {group.moderatorDescriptorPlural || this.props.t('Moderators')}
Privacy settings
+ {this.props.t('Privacy settings')}
Your group doesn't have a description
- {this.props.t('Your group doesn\'t have a description')}
+ {group.name} is only accessible to members of {group.prerequisiteGroups.map(prereq => {prereq.name})}
: {group.name} is only accessible to members of the following groups:
}
+ {group.prerequisiteGroups.length === 1 ? {group.name} is only accessible to members of {group.prerequisiteGroups.map(prereq => {prereq.name})}
: {this.props.t('{group.name} is only accessible to members of the following groups:', { group })}
} {/* TODO: Handle translation */}
{group.prerequisiteGroups.map(prereq => {q.text}
-
+
{q.text}
-
+
Which of the following skills & interests are relevant to you?
+ {t('Which of the following skills & interests are relevant to you?')}
Custom Views
- {this.props.t('Custom Views')}
+ Create new custom view
+ {this.props.t('Create new custom view')}
-
- Custom Views
-
+
- Create new custom view
-
+
Relevant skills & interests
- {this.props.t('Relevant skills & interests')}
+
- Relevant skills & interests
-
+
- You can select a CSV file to import posts into {name}. Posts will be created by you. The file must have columns with the following headers:
+ {this.props.t('You can select a CSV file to import posts into {{name}}. Posts will be created by you. The file must have columns with the following headers:', { name })}
-
- You can select a CSV file to import posts into
- Hylo
- . Posts will be created by you. The file must have columns with the following headers:
-
No new join requests
- We'll notify you by email when someone wants to join {group.name}
+ {t('No new join requests')}
+ {t('We\'ll notify you by email when someone wants to join {{group.name}}', { group })}
Visibility
- {this.props.t('Visibility')}
+ Access
- {this.props.t('Access')}
+ Prerequisite Groups
- {this.props.t('Prerequisite Groups')}
+ Group Access Questions
- {this.props.t('Group Access Questions')}
+ Hide {startCase(type)} Data
- {this.props.t('Hide {{type}} Data', { type: startCase(type) })}
+
- Visibility
-
+
- Access
-
+
- Prerequisite Groups
-
+
- Group Access Questions
-
+
{group.name} is a part of 1 Group
: '' }
- {parentGroups.length > 1 ? {group.name} is a part of {parentGroups.length} Groups
: '' }
+ {parentGroups.length === 1 ? {this.props.t('{{group.name}} is a part of 1 Group', { group })}
: '' }
+ {parentGroups.length > 1 ? {this.props.t('{{group.name}} is a part of {{parentGroups.length}} Groups', { group, parentGroups })}
: '' }
1 Group is a part of {group.name}
: ''}
- {childGroups.length > 1 ? {childGroups.length} groups are a part of {group.name}
: ''}
+ {childGroups.length === 1 ? {this.props.t('1 Group is a part of {{group.name}}', { group })}
: ''}
+ {childGroups.length > 1 ? {this.props.t('{{childGroups.length}} groups are a part of {{group.name}}', { childGroups, group })}
: ''}
{hasLocation && `${t('New Post at this location')}:`}{t('What would you like to create?')}
+ {hasLocation && t('New Post at this location:') + ' '}{t('What would you like to create?')}
{postTypes.map(postType => {
querystringParams.set('newPostType', postType)
diff --git a/src/routes/GroupSettings/CustomViewsTab/CustomViewsTab.js b/src/routes/GroupSettings/CustomViewsTab/CustomViewsTab.js
index 9e023f65e..9682b0267 100644
--- a/src/routes/GroupSettings/CustomViewsTab/CustomViewsTab.js
+++ b/src/routes/GroupSettings/CustomViewsTab/CustomViewsTab.js
@@ -283,11 +283,11 @@ function CustomViewRow ({
const sortOptions = type === 'collection' ? COLLECTION_SORT_OPTIONS : STREAM_SORT_OPTIONS
const defaultSortVal = defaultSort || (type === 'collection' ? 'order' : 'created')
-
+ const viewCount = parseInt(index) + 1
return (
-
Welcome to {group.name}!
+ {t('Welcome to {{group.name}}!', { group })}
{Object.keys(tabs).map(name =>
}
diff --git a/src/routes/MapExplorer/MapDrawer/MapDrawer.test.js b/src/routes/MapExplorer/MapDrawer/MapDrawer.test.js
index 8ce889f3b..18f62596c 100644
--- a/src/routes/MapExplorer/MapDrawer/MapDrawer.test.js
+++ b/src/routes/MapExplorer/MapDrawer/MapDrawer.test.js
@@ -4,6 +4,18 @@ import * as LayoutFlagsContext from 'contexts/LayoutFlagsContext'
import MapDrawer, { TabBar } from './MapDrawer'
+jest.mock('react-i18next', () => ({
+ ...jest.requireActual('react-i18next'),
+ useTranslation: (domain) => {
+ return {
+ t: (str) => str,
+ i18n: {
+ changeLanguage: () => new Promise(() => {})
+ }
+ }
+ }
+}))
+
const defaultMinProps = {
context: 'groups',
currentUser: { id: 1 },
From 5102fe7f8fe1c7de6624ba818467d6e82f18a5fe Mon Sep 17 00:00:00 2001
From: Sofia Acosta Save this view
- Get updates about this map view
+ {t('Save this view')}
+ {('Get updates about this map view')}
Saved Views
+ {t('Saved Views')}
{searches.map((search, index) => {
return (Messages
- : New Message
+ ? {this.props.t('Messages')}
+ : {this.props.t('New Message')}
}
New Message
+ {this.props.t('New Message')}
- Messages
-
+
- Messages
-
+
Sign in to Hylo
+ {t('Sign in to Hylo')}
{error && formatError(error, 'Login')}
@@ -85,7 +87,7 @@ export default function Login (props) {
/>
- Forgot password?
+ {t('Forgot password?')}
diff --git a/src/routes/NonAuthLayoutRouter/Login/Login.test.js b/src/routes/NonAuthLayoutRouter/Login/Login.test.js
index cba023111..5d2db91c6 100644
--- a/src/routes/NonAuthLayoutRouter/Login/Login.test.js
+++ b/src/routes/NonAuthLayoutRouter/Login/Login.test.js
@@ -2,6 +2,17 @@ import React from 'react'
import { render, screen } from 'util/testing/reactTestingLibraryExtended'
import Login from './Login'
+jest.mock('react-i18next', () => ({
+ ...jest.requireActual('react-i18next'),
+ useTranslation: (domain) => {
+ return {
+ t: (str) => str,
+ i18n: {
+ changeLanguage: () => new Promise(() => {})
+ }
+ }
+ }
+}))
it('renders correctly', () => {
render(
Sign in to Hylo
+ {t('Sign in to Hylo')}
{error && formatError(error, 'Login')}
Reset Your Password
+ {this.props.t('Reset Your Password')}
- Reset Your Password
-
+ />
Check your email
- {t('Check your email')}
+ Search
- {tabs.map(({ id, label }) => {t('Search')}
+ {tabs.map(({ id, label }) => setSearchFilter(id)}>
{label}
diff --git a/src/routes/Search/Search.test.js b/src/routes/Search/Search.test.js
index 1847d03d4..4145a78c0 100644
--- a/src/routes/Search/Search.test.js
+++ b/src/routes/Search/Search.test.js
@@ -2,6 +2,17 @@ import Search, { PersonCard } from './Search'
import { shallow } from 'enzyme'
import React from 'react'
+jest.mock('react-i18next', () => ({
+ ...jest.requireActual('react-i18next'),
+ useTranslation: (domain) => {
+ return {
+ t: (str) => str,
+ i18n: {
+ changeLanguage: () => new Promise(() => {})
+ }
+ }
+ }
+}))
describe('Search', () => {
it('matches the latest snapshot', () => {
const props = {
diff --git a/src/routes/UserSettings/AccountSettingsTab/AccountSettingsTab.js b/src/routes/UserSettings/AccountSettingsTab/AccountSettingsTab.js
index 788fcce7e..b392838b7 100644
--- a/src/routes/UserSettings/AccountSettingsTab/AccountSettingsTab.js
+++ b/src/routes/UserSettings/AccountSettingsTab/AccountSettingsTab.js
@@ -1,6 +1,7 @@
import { trim, pick, keys, omit, find, isEmpty } from 'lodash/fp'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
+import { withTranslation } from 'react-i18next'
import Button from 'components/Button'
import Loading from 'components/Loading'
@@ -12,7 +13,7 @@ import './AccountSettingsTab.scss'
import ModalDialog from 'components/ModalDialog'
const { object, func } = PropTypes
-export default class AccountSettingsTab extends Component {
+class AccountSettingsTab extends Component {
static propTypes = {
currentUser: object,
updateUserSettings: func,
@@ -78,7 +79,7 @@ export default class AccountSettingsTab extends Component {
})
}
- setConfirm('You have unsaved changes. Are you sure you want to leave?')
+ setConfirm(this.props.t('You have unsaved changes. Are you sure you want to leave?'))
this.setState({
changed: {
...changed,
@@ -103,9 +104,9 @@ export default class AccountSettingsTab extends Component {
const passwordConfirmed = password === confirm
- if (!validateEmail(email)) errors.push('Email address is not in a valid format')
- if (password.length > 0 && password.length < 9) errors.push('Passwords must be at least 9 characters long')
- if (!passwordConfirmed) errors.push('Passwords don\'t match')
+ if (!validateEmail(email)) errors.push(this.props.t('Email address is not in a valid format'))
+ if (password.length > 0 && password.length < 9) errors.push(this.props.t('Passwords must be at least 9 characters long'))
+ if (!passwordConfirmed) errors.push(this.props.t('Passwords don\'t match'))
return errors
}
@@ -130,21 +131,21 @@ export default class AccountSettingsTab extends Component {
const canSave = this.canSave()
return
- Deactivate
+ {this.props.t('Deactivate')}
- If you deactivate your account:
+ {this.props.t('If you deactivate your account:')}
-
- DELETE: CAUTION
+ {this.props.t('DELETE: CAUTION')}
- If you delete your account:
+ {this.props.t('If you delete your account:')}
-
Group Invitations & Join Requests
+ {this.props.t('Group Invitations & Join Requests')}
Invitations to Join New Groups
+ {this.props.t('Invitations to Join New Groups')}
Your Open Requests to Join Groups
+ {this.props.t('Your Open Requests to Join Groups')}
Declined Invitations & Requests
+ {this.props.t('Declined Invitations & Requests')}
- Group Invitations & Join Requests
-
+ />
- Invitations to Join New Groups
-
+ />
- Your Open Requests to Join Groups
-
+ />
- Declined Invitations & Requests
-
+ />
diff --git a/src/routes/UserSettings/NotificationSettingsTab/NotificationSettingsTab.js b/src/routes/UserSettings/NotificationSettingsTab/NotificationSettingsTab.js
index 4bc9d8c75..05206951e 100644
--- a/src/routes/UserSettings/NotificationSettingsTab/NotificationSettingsTab.js
+++ b/src/routes/UserSettings/NotificationSettingsTab/NotificationSettingsTab.js
@@ -1,4 +1,5 @@
import React, { Component } from 'react'
+import { useTranslation, withTranslation } from 'react-i18next'
import PropTypes from 'prop-types'
import './NotificationSettingsTab.scss'
import Loading from 'components/Loading'
@@ -15,7 +16,7 @@ const { object, func } = PropTypes
const iOSAppURL = 'https://itunes.apple.com/app/appName/id1002185140'
const androidAppURL = 'https://play.google.com/store/apps/details?id=com.hylo.hyloandroid'
-export default class NotificationSettingsTab extends Component {
+class NotificationSettingsTab extends Component {
static propTypes = {
currentUser: object,
updateUserSettings: func
@@ -52,11 +53,11 @@ export default class NotificationSettingsTab extends Component {
updateAllGroupsAlert = changes => {
const key = ('sendEmail' in changes) ? 'sendEmail' : 'sendPushNotifications'
- const type = key === 'sendEmail' ? 'Email' : 'Push Notifications'
- const onOrOff = changes[key] ? 'ON' : 'OFF'
+ const type = key === 'sendEmail' ? this.props.t('Email') : this.props.t('Push Notifications')
+ const onOrOff = changes[key] ? this.props.t('ON') : this.props.t('OFF')
const numGroups = this.props.memberships.length
- if (window.confirm(`You wish to turn ${onOrOff} ${type} for all groups? This will affect ${numGroups} ${numGroups === 1 ? 'group' : 'groups'}`)) {
+ if (window.confirm(this.props.t(`You wish to turn {{onOrOff}} {{type}} for all groups? This will affect {{numGroups}} {groups}.`, { onOrOff, type, numGroups, groups: numGroups === 1 ? this.props.t('group') : this.props.t('groups') }))) {
this.updateAllGroups(changes)
}
}
@@ -88,20 +89,20 @@ export default class NotificationSettingsTab extends Component {
}
return Your affiliations with organizations
+ {this.props.t('Your affiliations with organizations')}
- Hylo Groups
+ {this.props.t('Hylo Groups')}
{action === LEAVE_GROUP && displayMessage && Other Affiliations
+ {this.props.t('Other Affiliations')}
{action === DELETE_AFFILIATION && displayMessage && Add new affiliation
+ {this.props.t('Add new affiliation')}
- Your affiliations with organizations
-
+ />
- Hylo Groups
-
+ />
- Other Affiliations
-
+ />
Upload a profile image
- {this.props.t('Upload a profile image')}
+ Welcome to Hylo!
+ {this.props.t('Welcome to Hylo!')}
View the public map
- {this.props.t('View the public map')}
+ Public stream
- {this.props.t('Public stream')}
+ Create a group
- {this.props.t('Create a group')}
+ Complete your profile
- {this.props.t('Complete your profile')}
+
- Welcome to Hylo!
-
+
- View the public map
-
-
- Public stream
-
-
- Create a group
-
-
- Complete your profile
-
- Explanation for Flagging
+ {this.props.t('Explanation for Flagging')}
How do we use cookies?
- Hylo login & session
- Mixpanel
- Optimizely
- Intercom
- Local storage & cache
- {t('How do we use cookies?')}
+ {t('Hylo login & session')}
+ {t('Mixpanel')}
+ {t('Optimizely')}
+ {t('Intercom')}
+ {t('Local storage & cache')}
+ {group?.name} Group Shape
+ {group?.name} {t('Group Shape')}
+ Custom Views
+
+ >
+ Add custom links or filtered post views to your group's navigation
+
+ Create new custom view
+
+ Relevant skills & interests
+
+ >
+ What skills and interests are particularly relevant to this group?
+
+ You can select a CSV file to import posts into {{name}}. Posts will be created by you. The file must have columns with the following headers:
-
-
-
-
-
-
-
-
-
+
+ Visibility
+
+ >
+ Who is able to see <strong>{{name}}</strong>?
+
@@ -117,10 +129,14 @@ exports[`PrivacySettingsTab renders correctly 1`] = ` />