Skip to content

Commit

Permalink
➕ Add support for translations in OpenLyrics XML exports
Browse files Browse the repository at this point in the history
  • Loading branch information
devmount committed Jun 13, 2024
1 parent 0663c9b commit b3730f2
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 17 deletions.
13 changes: 9 additions & 4 deletions frontend/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ const browserPrefersDark = () => {
const mailto = (address) => window.location.href = 'mailto:' + address;

// build OpenLyrics XML for given song
const openLyricsXML = (song, version, locales = [], allTags = null) => {
const openLyricsXML = (song, version, translatedSong = null, locales = [], allTags = null) => {
const timestamp = (new Date()).toISOString().slice(0, -5);
const title = `<title>${song.title}</title>`;
const subtitle = song.subtitle ? `<title>${song.subtitle}</title>` : '';
Expand All @@ -348,13 +348,18 @@ const openLyricsXML = (song, version, locales = [], allTags = null) => {
tag => locales.map(l =>`<theme lang="${l}">${allTags[tag][l] ?? tag.key}</theme>`).join('')
).join('') + '</themes>'
: '';
const lyrics = parsedContent(song.content, song.tuning, false, false).map(p => {
const format = translatedSong ? `<format><tags application='OpenLP'><tag name='it'><open>&lt;em&gt;</open><close>&lt;/em&gt;</close><hidden>False</hidden></tag><tag name='gr'><open>&lt;span style='-webkit-text-fill-color:#c2c2a3'&gt;</open><close>&lt;/span&gt;</close><hidden>False</hidden></tag></tags></format>` : '';
const tParts = translatedSong ? parsedContent(translatedSong.content, 0, false, false) : [];
const lyrics = parsedContent(song.content, 0, false, false).map((p, i) => {
const type = p.type ? p.type.toUpperCase() : 'V';
const num = p.number > 0 ? p.number : '1';
return `<verse name='${type}${num}'><lines>` + p.content.replace(/\n/g, "<br />") + '</lines></verse>'
const tContent = (i in tParts)
? `<br/><br/><tag name='it'><tag name='gr'>${tParts[i].content.replace(/\n/g, "<br />")}</tag></tag>`
: '';
return `<verse name='${type}${num}'><lines>${p.content.replace(/\n/g, "<br />")}${tContent}</lines></verse>`;
}).join('');

return `<?xml version='1.0' encoding='UTF-8'?><song xmlns='http://openlyrics.info/namespace/2009/song' version='0.9' createdIn='SongDrive ${version}' modifiedIn='SongDrive ${version}' modifiedDate='${timestamp}'><properties><titles>${title}${subtitle}</titles>${copyright}${year}${ccli}${authors}${tags}</properties><lyrics>${lyrics}</lyrics></song>`;
return `<?xml version='1.0' encoding='UTF-8'?><song xmlns='http://openlyrics.info/namespace/2009/song' version='0.9' createdIn='SongDrive ${version}' modifiedIn='SongDrive ${version}' modifiedDate='${timestamp}'><properties><titles>${title}${subtitle}</titles>${copyright}${year}${ccli}${authors}${tags}</properties>${format}<lyrics>${lyrics}</lyrics></song>`;
};

export {
Expand Down
32 changes: 20 additions & 12 deletions frontend/src/views/SetlistShow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -545,13 +545,13 @@ const emit = defineEmits(['editSong', 'editSetlist']);
// component properties
const props = defineProps({
languages: Object,
ready: Object,
role: Number,
setlists: Object,
songs: Object,
user: String,
users: Object,
languages: Object,
ready: Object,
role: Number,
setlists: Object,
songs: Object,
user: String,
users: Object,
});
// reactive data
Expand Down Expand Up @@ -981,12 +981,20 @@ const exportOsz = async () => {
if (setlist.value.songs.hasOwnProperty(key) && setlist.value.songs[key].id in props.songs) {
// get song object
const song = props.songs[setlist.value.songs[key].id];
// check for translations
const lang = !('lang' in localStorage) ? locale.value : localStorage.getItem('lang');
let tSong = null;
if (lang !== song.language && song.translations.length > 0) {
const tKey = song.translations.find((t) => t.endsWith(`-${lang}`));
tSong = props.songs[tKey];
}
// handle song content parts
let itemData = [];
let parts = parsedContent(song.content, 0, false, false);
parts.forEach((part) => {
const itemData = [];
const parts = parsedContent(song.content, 0, false, false);
const tParts = tSong ? parsedContent(tSong.content, 0, false, false) : [];
parts.forEach((part, i) => {
itemData.push({
'raw_slide': part.content,
'raw_slide': (i in tParts) ? part.content + "\n\n" + tParts[i].content : part.content,
'verseTag': (part.type ? part.type.toUpperCase() : 'V') + (part.number > 0 ? part.number.toString() : '1'),
});
});
Expand Down Expand Up @@ -1014,7 +1022,7 @@ const exportOsz = async () => {
'ccli_number': song.ccli,
'copyright': song.publisher
},
'xml_version': openLyricsXML(song, version),
'xml_version': openLyricsXML(song, version, tSong),
'auto_play_slides_once': false,
'auto_play_slides_loop': false,
'timed_slide_interval': 0,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/views/SongShow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ const exportSng = () => {
// export song in OpenLyrics XML format
const exportXml = () => {
// start download
download(openLyricsXML(song.value, version, availableLocales, props.tags), songId + '.xml');
download(openLyricsXML(song.value, version, null, availableLocales, props.tags), songId + '.xml');
// toast success message
notify({
title: t('toast.exportedXml'),
Expand Down

0 comments on commit b3730f2

Please sign in to comment.