the-amazing-quran-translations
Version:
This repository contains translations of the holly Quran in json format, and a small node module to handle them
371 lines (325 loc) • 13.9 kB
JavaScript
/**
* This module is a simple handler to get surah and ayah of the holly Quran in different language.
* See available languages in config.json file.
*
* Directory structure required :
* dir/
* translationsManager.js
* config.json
* translations/
* quran-[languageName].json
* // if the translator name is known
* quran-[languageName]-[translatorName].json
*
*
* LANGINFOS OBJECT
* {
* "language": String,
* "translationAuthor": Array of String
* }
*
* SURAH OBJECT
* Return of getSurah
* {
* surahNumber: String,
* surahName: String,
* translatedSurahNames: Object,
* ayahs: Array[{ ayahNumber: String, ayahContent: String, translationName: string }]
* }
*
* example:
* var foo = getSurah(112, [{ languageName: 'french'}, {languageName: 'english', authorName: 'Yusuf_Ali'}, {languageName: 'chinese'}]);
*
* console.log(foo);
* // Will display :
* {
* surahNumber: '112',
* surahName: 'الإخلاص',
* translatedSurahNames:
* {
* french: 'Le monothéisme pur (Al-Ihlas)',
* english: 'The Unity',
* chinese: '忠 誠'
* },
* ayahs:
* [ { ayahNumber: '1',
* ayahContent: 'قُلْ هُوَ اللَّهُ أَحَدٌ',
* french: 'Dis : "Il est Allah, Unique.',
* english: 'Say: He is Allah, the One and Only;',
* chinese: '你說:他是真主,是獨一的主;' },
* { ayahNumber: '2',
* ayahContent: 'اللَّهُ الصَّمَدُ',
* french: 'Allah, Le Seul à être imploré pour ce que nous désirons.',
* english: 'Allah, the Eternal, Absolute;',
* chinese: '真主是萬物所仰賴的;' },
* { ayahNumber: '3',
* ayahContent: 'لَمْ يَلِدْ وَلَمْ يُولَدْ',
* french: 'Il n´a jamais engendré, n´a pas été engendré non plus.',
* english: 'He begetteth not, nor is He begotten;',
* chinese: '他沒有生產,也沒有被生產;' },
* { ayahNumber: '4',
* ayahContent: 'وَلَمْ يَكُنْ لَهُ كُفُوًا أَحَدٌ',
* french: 'Et nul n´est égal à Lui".',
* english: 'And there is none like unto Him.',
* chinese: '沒有任何物可以做他的匹敵。' }
* ]
* }
*
* AYAH OBJECT
* Return of getAyah
* {
* ayahNumber: String,
* ayahContent: String,
* translationName: String,
* surah: Object { surahNumber: String, surahName: String, translatedSurahNames: Object }
* }
* example :
* var bar = getAyah(7, 43, 'french');
* console.log(bar);
*
* // Will display
* { ayahNumber: '43',
* ayahContent: 'وَنَزَعْنَا مَا فِي صُدُورِهِمْ مِنْ غِلٍّ تَجْرِي مِنْ تَحْتِهِمُ الْأَنْهَارُ ۖ وَقَالُوا الْحَمْدُ لِلَّهِ الَّذِي هَدَانَا لِهَٰذَا وَمَا كُنَّا لِنَهْتَدِيَ لَوْلَا أَنْ هَدَانَا اللَّهُ ۖ لَقَدْ جَاءَتْ رُسُلُ رَبِّنَا بِالْحَقِّ ۖ وَنُودُوا أَنْ تِلْكُمُ الْجَنَّةُ أُورِثْتُمُوهَا بِمَا كُنْتُمْ تَعْمَلُونَ',
* french: 'Et Nous enlèverons toute la rancune de leurs poitrines, sous eux couleront les ruisseaux, et ils diront : "Louange à Allah qui nous a guidés à ceci. Nous n´aurions pas été guidés, si Allah ne nous avait pas guidés. Les messagers de notre Seigneur sont venus avec la vérité." Et on leur proclamera : "Voilà le Paradis qui vous a été donné en héritage pour ce que vous faisiez".',
* surah:
* {
* surahNumber: '7',
* surahName: 'الأعراف',
* translatedSurahNames: { french: 'Al-Araf'
* }
* }
*/
(() => { 'use strict';
const _ = require('lodash');
const config = require('./config.json');
const deepcopy = require('deepcopy');
module.exports = () => {
const _availableTranslations = _.pluck(config.translations, 'language');
const _defaultLanguage = deepcopy(_.find(config.translations, (langInfos) => langInfos.language === 'arabic'));
const _arabicQuran = {
language: 'arabic',
filePath: _getFilePath('arabic'),
content: require(_getFilePath('arabic')),
};
let model = {};
let _translations = [];
model.getAvailableLanguages = getAvailableLanguages;
model.getAyah = getAyah;
model.getSurah = getSurah;
/**
* Return the good language settings. If bad entry, return arabic.
* @param {String} language
* @return {Object} Language informations
*/
function _getLanguage(language) {
return _.find(config.translations, (langInfos) => langInfos.language === language) || _defaultLanguage;
}
/**
* Return the translation author when exist or default translation.
* @param {Object} langInfos
* @param {String} authorName
* @return {String} Author name
*/
function _getTranslationAuthor(langInfos, authorName) {
let author = '';
if (langInfos.translationAuthor) {
if (authorName) {
author = _.find(langInfos.translationAuthor, (author) => {
return author.toLowerCase() === authorName.toLowerCase() ;
});
}
author = author || langInfos.translationAuthor[0];
}
return author;
}
/**
* Return the good file path. By default and on bad entry, return arabic.
* @param {String} language
* @param {String} translationAuthor
* @return {String} The path to the json file
*/
function _getFilePath(language, translationAuthor) {
let langInfos = _getLanguage(language);
let author = _getTranslationAuthor(langInfos, translationAuthor);
author = (author) ? ('-' + author) : '';
return config.path + config.prefix + langInfos.language + author + '.json';
}
/**
* Return the translated version of quran
* @param {String} language
* @param {String} translationAuthor
* @return {Object} Quran translated. By defaut and on bad entry return arabic.
*/
function _getTranslation(language, translationAuthor) {
let langInfos = _getLanguage(language); // to avoid bad entry
if (langInfos.language === 'arabic') return _arabicQuran;
// Check if a translation author exist for the language
let author = _getTranslationAuthor(langInfos, translationAuthor);
// Get back the translation if already exist
let translation = _.find(_translations, trnsl => {
let match = (trnsl.language === language);
if (trnsl.author) match = (trnsl.author === author);
return match;
});
// If not, we create a new translation object and put it in memory
if (!translation) {
let filePath = _getFilePath(langInfos.language, author);
let newNode = {
language: langInfos.language,
filePath: filePath,
content: require(filePath),
};
if (author) newNode.author = author;
_translations.push(newNode);
return newNode;
}
return translation;
}
/**
* Check if the surah number is valid
* @param {Int} surahNumber
* @return {Boolean} Exist or not
*/
function _checkSurahNumber(surahNumber) {
return (parseInt(surahNumber) > 0 && parseInt(surahNumber) < 115);
}
/**
* Check if the ayah number is valid
* @param {Int || String} ayahNumber
* @param {Int || String} ayahLength
* @return {Boolean} Exist or not
*/
function _checkAyahNumber(ayahNumber, ayahLength) {
return (parseInt(ayahNumber) > 0 && parseInt(ayahNumber) <= parseInt(ayahLength));
}
/**
* Format the languages parameter of getSurah and getAyah to be an array
* of string.
* @param {[type]} languages [description]
* @return {[type]} [description]
*/
function _getFormatedTranslationsList(languages) {
let languagesList = [];
if (!Array.isArray(languages) && typeof languages === 'object') languagesList.push(languages);
if (typeof languages === 'string') {
let languagesNames = languages.split(',');
languagesNames.forEach(name => {
languagesList.push({ languageName: name});
});
}
return languagesList;
}
/**
* Return the translation of an ayah
* by default or error in language return arabic
* @param {String} surahNumber [description]
* @param {String} ayahNumber [description]
* @param {String} language [description]
* @param {String} translationAuthor [description]
* @return {String} [description]
*/
function _getAyahTranslation(surahNumber, ayahNumber, language) {
if (_checkSurahNumber(surahNumber)) {
let quran = _getTranslation(language.languageName, language.authorName);
let surah = deepcopy(_.find(quran.content, surah => surah.surahNumber === String(surahNumber)));
if (surah) {
if (_checkAyahNumber(ayahNumber, surah.ayahs.length)) {
let translatedAyah = deepcopy(_.find(surah.ayahs, ayah => ayah.ayahNumber === String(ayahNumber)));
return translatedAyah.ayahContent;
}
}
}
return false;
}
/**
* Return the translation of the surah name
* @param {String} surahNumber [description]
* @param {String} language [description]
* @param {String} translationAuthor [description]
* @return {String} [description]
*/
function _getTranslatedSurahName(surahNumber, language) {
if (_checkSurahNumber(surahNumber)) {
let quran = _getTranslation(language.languageName, language.authorName);
let surah = deepcopy(_.find(quran.content, surah => surah.surahNumber === String(surahNumber)));
if (surah) return surah.surahName;
}
return false;
}
/**
* Return the list of the available languages
* @return {Array} Array of string
*/
function getAvailableLanguages() { return _availableTranslations; }
/**
* Return the wanted surah
* @param {String || Int} surahNumber
* @param {String || Object || Array[Object]} languages
* @return {Object} The surah if exist with translations if needed
*/
function getSurah(surahNumber, languages) {
surahNumber = parseInt(surahNumber);
if (_checkSurahNumber(surahNumber)) {
// we retreive the surah in arabic
let surah = deepcopy(_.find(_arabicQuran.content, surah => surah.surahNumber === String(surahNumber)));
languages = _getFormatedTranslationsList(languages);
// for each languages (if exist), we retreive translation of ayahs and the surah name
languages.forEach(lang => {
if (_availableTranslations.indexOf(lang.languageName) !== -1) {
let translatedSurahName = _getTranslatedSurahName(surah.surahNumber, lang);
if (translatedSurahName !== surah.surahName) {
surah.translatedSurahNames = surah.translatedSurahNames || {};
surah.translatedSurahNames[lang.languageName] = translatedSurahName;
}
surah.ayahs.forEach(ayah => {
let translatedAyah = _getAyahTranslation(surah.surahNumber, ayah.ayahNumber, lang);
if (translatedAyah !== ayah.ayahContent) ayah[lang.languageName] = translatedAyah;
});
}
});
return surah;
}
return false;
}
/**
* Return the ayah if exist with translations if required
* @param {Int || String} surahNumber
* @param {Int || String} ayahNumber
* @param {String || Object || Array[Object]} languages
* @return {Object} Ayah object if surahNumber and ayahNumber are valid
*/
function getAyah(surahNumber, ayahNumber, languages) {
surahNumber = parseInt(surahNumber);
ayahNumber = parseInt(ayahNumber);
if (_checkSurahNumber(surahNumber)) {
// we retreive the surah in arabic
let surah = deepcopy(_.find(_arabicQuran.content, surah => surah.surahNumber === String(surahNumber)));
languages = _getFormatedTranslationsList(languages);
if (surah) {
if (_checkAyahNumber(ayahNumber, surah.ayahs.length)) {
let ayah = deepcopy(_.find(surah.ayahs, ayah => ayah.ayahNumber === String(ayahNumber)));
ayah.surah = {
surahNumber: surah.surahNumber,
surahName: surah.surahName
};
// for each languages (if exist), we retreive translation of the ayah and the surah name
languages.forEach(lang => {
if (_availableTranslations.indexOf(lang.languageName) !== -1) {
let translatedAyah = _getAyahTranslation(surah.surahNumber, ayah.ayahNumber, lang);
let translatedSurahName = _getTranslatedSurahName(surah.surahNumber, lang);
if (translatedAyah !== ayah.ayahContent) ayah[lang.languageName] = translatedAyah;
if (translatedSurahName !== surah.surahName) {
ayah.surah.translatedSurahNames = ayah.surah.translatedSurahNames || {};
ayah.surah.translatedSurahNames[lang.languageName] = translatedSurahName;
}
}
});
return ayah;
}
}
}
return false;
}
return model;
};
})();