Skip to content
This repository was archived by the owner on Jun 28, 2021. It is now read-only.

Commit 68f4acd

Browse files
naveed-ahmadahmedre
authored andcommitted
Translation url (#797)
* added translation id in share url * added routes for surah with translation * split translations if its string * added translation aware routes in sitemap! SEO
1 parent 45ef788 commit 68f4acd

File tree

7 files changed

+155
-78
lines changed

7 files changed

+155
-78
lines changed

Diff for: src/components/Share/index.js

+19-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { PropTypes } from 'react';
1+
import React from 'react';
22
import { ShareButtons, generateShareIcon } from 'react-share';
33
import * as customPropTypes from 'customPropTypes';
44

@@ -8,12 +8,24 @@ const { FacebookShareButton, TwitterShareButton } = ShareButtons;
88
const FacebookIcon = generateShareIcon('facebook');
99
const TwitterIcon = generateShareIcon('twitter');
1010

11-
const Share = ({ chapter, verseKey }) => {
11+
const Share = ({ chapter, verse }) => {
1212
// Fallback to Surah Id
13-
const path = verseKey ? verseKey.replace(':', '/') : chapter.chapterNumber;
13+
let path;
14+
15+
if (verse) {
16+
const translations = (verse.translations || [])
17+
.map(translation => translation.resourceId)
18+
.join(',');
19+
path = `${verse.chapterId}/${verse.verseNumber}?translations=${translations}`;
20+
} else {
21+
path = chapter.chapterNumber;
22+
}
23+
1424
const shareUrl = `https://quran.com/${path}`;
15-
const title = verseKey ? `Surah ${chapter.nameSimple} [${verseKey}]` : `Surah ${chapter.nameSimple}`;
16-
const iconProps = verseKey ? { iconBgStyle: { fill: '#d1d0d0' } } : {};
25+
const title = verse
26+
? `Surah ${chapter.nameSimple} [${verse.verseKey}]`
27+
: `Surah ${chapter.nameSimple}`;
28+
const iconProps = verse ? { iconBgStyle: { fill: '#d1d0d0' } } : {};
1729

1830
return (
1931
<div className={`${styles.shareContainer}`}>
@@ -38,8 +50,8 @@ const Share = ({ chapter, verseKey }) => {
3850
};
3951

4052
Share.propTypes = {
41-
verseKey: PropTypes.string,
42-
chapter: customPropTypes.surahType.isRequired
53+
chapter: customPropTypes.surahType.isRequired,
54+
verse: customPropTypes.verseType
4355
};
4456

4557
export default Share;

Diff for: src/components/Verse/index.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,11 @@ class Verse extends Component {
251251
);
252252
}
253253

254-
renderAyahBadge() {
254+
renderBadge() {
255255
const { isSearched, verse } = this.props;
256+
const translations = (verse.translations || [])
257+
.map(translation => translation.resourceId)
258+
.join(',');
256259
let metric;
257260

258261
const content = (
@@ -271,7 +274,7 @@ class Verse extends Component {
271274

272275
return (
273276
<Link
274-
to={`/${verse.chapterId}/${verse.verseNumber}`}
277+
to={`/${verse.chapterId}/${verse.verseNumber}?translations=${translations}`}
275278
data-metrics-event-name={metric}
276279
>
277280
{content}
@@ -284,15 +287,15 @@ class Verse extends Component {
284287

285288
if (isSearched) return false;
286289

287-
return <Share chapter={chapter} verseKey={verse.verseKey} />;
290+
return <Share chapter={chapter} verse={verse} />;
288291
}
289292

290293
renderControls() {
291294
const { isPdf } = this.props;
292295

293296
return (
294297
<div className={`col-md-1 col-sm-1 ${styles.controls}`}>
295-
{this.renderAyahBadge()}
298+
{this.renderBadge()}
296299
{this.renderPlayLink()}
297300
{this.renderCopyLink()}
298301
{this.renderBookmark()}

Diff for: src/containers/Surah/connect.js

+17-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
clearCurrent,
1111
load as loadVerses,
1212
isLoaded
13-
} from 'redux/actions/verses.js';
13+
} from 'redux/actions/verses.js';
1414

1515
import { debug } from 'helpers';
1616

@@ -57,7 +57,10 @@ export const chaptersConnect = ({ store: { getState, dispatch } }) => {
5757
return dispatch(loadAll());
5858
};
5959

60-
export const chapterInfoConnect = ({ store: { dispatch, getState }, params }) => {
60+
export const chapterInfoConnect = ({
61+
store: { dispatch, getState },
62+
params
63+
}) => {
6164
if (isInfoLoaded(getState(), params.chapterId)) return false;
6265

6366
if (__CLIENT__) {
@@ -68,11 +71,16 @@ export const chapterInfoConnect = ({ store: { dispatch, getState }, params }) =>
6871
return dispatch(loadInfo(params));
6972
};
7073

71-
export const versesConnect = ({ store: { dispatch, getState }, params }) => {
74+
export const versesConnect = ({
75+
store: { dispatch, getState },
76+
params,
77+
location
78+
}) => {
7279
debug('component:Surah:versesConnect', 'Init');
7380

7481
const chapterId = parseInt(params.chapterId, 10);
7582
const paging = determinePage(params.range);
83+
const translations = params.translations || location.query.translations;
7684

7785
if (chapterId !== getState().chapters.current) {
7886
dispatch(setCurrentSurah(chapterId));
@@ -84,11 +92,15 @@ export const versesConnect = ({ store: { dispatch, getState }, params }) => {
8492
dispatch(clearCurrent(chapterId)); // In the case where you go to same surah but later ayahs.
8593

8694
if (__CLIENT__) {
87-
dispatch(loadVerses(chapterId, paging, getState().options));
95+
dispatch(
96+
loadVerses(chapterId, paging, { translations }, getState().options)
97+
);
8898
return true;
8999
}
90100

91-
return dispatch(loadVerses(chapterId, paging, getState().options));
101+
return dispatch(
102+
loadVerses(chapterId, paging, { translations }, getState().options)
103+
);
92104
}
93105

94106
return true;

Diff for: src/containers/Surah/index.js

+23-5
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,17 @@ class Surah extends Component {
203203
}
204204

205205
renderPagination() {
206-
const { isSingleAyah, isLoading, isEndOfSurah, chapter } = this.props;
206+
const {
207+
isSingleAyah,
208+
isLoading,
209+
isEndOfSurah,
210+
chapter,
211+
verses,
212+
currentVerse
213+
} = this.props;
214+
const translations = (verses[currentVerse].translations || [])
215+
.map(translation => translation.resourceId)
216+
.join(',');
207217

208218
// If single verse, eh. /2/30
209219
if (isSingleAyah) {
@@ -214,7 +224,9 @@ class Surah extends Component {
214224
return (
215225
<ul className="pager">
216226
<li className="text-center">
217-
<Link to={`/${chapter.chapterNumber}/${this.getFirst()}-${to}`}>
227+
<Link
228+
to={`/${chapter.chapterNumber}/${this.getFirst()}-${to}?translations=${translations}`}
229+
>
218230
<LocaleFormattedMessage
219231
id="chapter.index.continue"
220232
defaultMessage="Continue"
@@ -234,7 +246,9 @@ class Surah extends Component {
234246
<ul className="pager">
235247
{chapter.chapterNumber > 1 &&
236248
<li className="previous">
237-
<Link to={`/${chapter.chapterNumber * 1 - 1}`}>
249+
<Link
250+
to={`/${chapter.chapterNumber * 1 - 1}?translations=${translations}`}
251+
>
238252
239253
<LocaleFormattedMessage
240254
id="chapter.previous"
@@ -243,7 +257,9 @@ class Surah extends Component {
243257
</Link>
244258
</li>}
245259
<li className="text-center">
246-
<Link to={`/${chapter.chapterNumber}`}>
260+
<Link
261+
to={`/${chapter.chapterNumber}?translations=${translations}`}
262+
>
247263
<LocaleFormattedMessage
248264
id="chapter.goToBeginning"
249265
defaultMessage="Beginning of Surah"
@@ -252,7 +268,9 @@ class Surah extends Component {
252268
</li>
253269
{chapter.chapterNumber < 114 &&
254270
<li className="next">
255-
<Link to={`/${chapter.chapterNumber * 1 + 1}`}>
271+
<Link
272+
to={`/${chapter.chapterNumber * 1 + 1}?translations=${translations}`}
273+
>
256274
<LocaleFormattedMessage
257275
id="chapter.next"
258276
defaultMessage="Next Surah"

Diff for: src/redux/actions/verses.js

+18-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,23 @@ const defaultOptions = {
1818
// NOTE: From the API!
1919
const perPage = 10;
2020

21-
export function load(id, paging, options = defaultOptions) {
22-
const { translations } = options;
21+
function prepareParams(params, options) {
22+
// NOTE: first priority to options in URL, second to options and lastly fallback to defaultOptions
23+
let translations;
24+
25+
if (params.translations && params.translations.length) {
26+
translations = typeof params.translations === 'string'
27+
? params.translations.split(',')
28+
: params.translations;
29+
} else {
30+
translations = options.translations || defaultOptions.translations;
31+
}
32+
33+
return { translations };
34+
}
35+
36+
export function load(id, paging, params, options = defaultOptions) {
37+
const apiOptions = prepareParams(params, options);
2338

2439
// TODO: move this to module/verses
2540
// cookie.save('lastVisit', JSON.stringify({ chapterId: id, verseId: from }));
@@ -31,7 +46,7 @@ export function load(id, paging, options = defaultOptions) {
3146
client.get(`/api/v3/chapters/${id}/verses`, {
3247
params: {
3348
...paging,
34-
translations
49+
...apiOptions
3550
}
3651
}),
3752
chapterId: id

Diff for: src/routes.js

+14
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,20 @@ export default (store) => {
153153
.catch(err => console.trace(err))}
154154
/>
155155

156+
<Route
157+
path="/:chapterId/:range/:translations"
158+
getComponents={(nextState, cb) =>
159+
Promise.all([
160+
import('./containers/Surah'),
161+
import('./components/GlobalNav/Surah')
162+
])
163+
.then(modules =>
164+
cb(null, { main: modules[0].default, nav: modules[1].default })
165+
)
166+
.catch(err => console.trace(err))}
167+
onEnter={checkValidSurah}
168+
/>
169+
156170
<Redirect from="/:chapterId:(:range)" to="/:chapterId(/:range)" />
157171
<Redirect from="/:chapterId/:from::to" to="/:chapterId/:from-:to" />
158172

Diff for: src/server/config/sitemap.js

+57-54
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,81 @@ export default (server) => {
88
const urls = [];
99

1010
client
11-
.get('/api/v3/chapters')
12-
.then((response) => {
13-
response.chapters.forEach((chapter) => {
14-
Array(chapter.verses_count).fill().forEach((_, index) => {
15-
const verseId = index + 1;
11+
.get('/api/v3/options/translations')
12+
.then((r) => {
13+
const translations = r.translations;
14+
client.get('/api/v3/chapters').then((response) => {
15+
response.chapters.forEach((chapter) => {
16+
Array(chapter.verses_count).fill().forEach((_, index) => {
17+
const verseId = index + 1;
1618

17-
urls.push({
18-
url: `/${chapter.id}/${verseId}`,
19-
changefreq: 'weekly',
20-
priority: 1
19+
urls.push({
20+
url: `/${chapter.id}/${verseId}`,
21+
changefreq: 'weekly',
22+
priority: 1
23+
});
24+
25+
urls.push({
26+
url: `/${chapter.id}/${verseId}-${verseId + 9}`,
27+
changefreq: 'weekly',
28+
priority: 1
29+
});
30+
31+
// Add verse url with translations
32+
translations.forEach((translation) => {
33+
urls.push({
34+
url: `/${chapter.id}/${verseId}/${translation.slug || translation.id}`,
35+
changefreq: 'weekly',
36+
priority: 1
37+
});
38+
39+
urls.push({
40+
url: `/${chapter.id}/${verseId + 9}/${translation.slug || translation.id}`,
41+
changefreq: 'weekly',
42+
priority: 1
43+
});
44+
});
2145
});
2246

2347
urls.push({
24-
url: `/${chapter.id}/${verseId}-${verseId + 9}`,
48+
url: `/${chapter.id}`,
2549
changefreq: 'weekly',
2650
priority: 1
2751
});
28-
});
29-
30-
urls.push({
31-
url: `/${chapter.id}`,
32-
changefreq: 'weekly',
33-
priority: 1
34-
});
35-
36-
urls.push({
37-
url: `/${chapter.id}/info/ur`,
38-
changefreq: 'weekly',
39-
priority: 1
40-
});
4152

42-
urls.push({
43-
url: `/${chapter.id}/info/ml`,
44-
changefreq: 'weekly',
45-
priority: 1
53+
// add chapter info for available languages
54+
['en', 'ur', 'ml', 'ta'].forEach((lang) => {
55+
urls.push({
56+
url: `/${chapter.id}/info/${lang}`,
57+
changefreq: 'weekly',
58+
priority: 1
59+
});
60+
});
4661
});
4762

4863
urls.push({
49-
url: `/${chapter.id}/info/ta`,
64+
url: '/ayatul-kursi',
5065
changefreq: 'weekly',
5166
priority: 1
5267
});
5368

54-
urls.push({
55-
url: `/${chapter.id}/info/en`,
56-
changefreq: 'weekly',
57-
priority: 1
69+
const xml = sitemap.createSitemap({
70+
hostname: 'https://quran.com',
71+
cacheTime: 600000, // 600 sec cache period
72+
urls: [
73+
...urls,
74+
{ url: '/about', changefreq: 'monthly', priority: 0.3 },
75+
{ url: '/contactus', changefreq: 'monthly', priority: 0.3 },
76+
{ url: '/contact', changefreq: 'monthly', priority: 0.3 },
77+
{ url: '/donations', changefreq: 'monthly', priority: 0.3 },
78+
{ url: '/contributions', changefreq: 'monthly', priority: 0.3 },
79+
{ url: '/search', changefreq: 'weekly', priority: 0.8 }
80+
]
5881
});
59-
});
6082

61-
urls.push({
62-
url: '/ayatul-kursi',
63-
changefreq: 'weekly',
64-
priority: 1
83+
res.header('Content-Type', 'application/xml');
84+
res.send(xml.toString());
6585
});
66-
67-
const xml = sitemap.createSitemap({
68-
hostname: 'https://quran.com',
69-
cacheTime: 600000, // 600 sec cache period
70-
urls: [
71-
...urls,
72-
{ url: '/about', changefreq: 'monthly', priority: 0.3 },
73-
{ url: '/contactus', changefreq: 'monthly', priority: 0.3 },
74-
{ url: '/contact', changefreq: 'monthly', priority: 0.3 },
75-
{ url: '/donations', changefreq: 'monthly', priority: 0.3 },
76-
{ url: '/contributions', changefreq: 'monthly', priority: 0.3 },
77-
{ url: '/search', changefreq: 'weekly', priority: 0.8 }
78-
]
79-
});
80-
81-
res.header('Content-Type', 'application/xml');
82-
res.send(xml.toString());
8386
})
8487
.catch(err => console.trace(err)); // eslint-disable-line
8588
});

0 commit comments

Comments
 (0)