Skip to content

Commit

Permalink
HTML Setup: Enable translation in mythbackend and setup menu.
Browse files Browse the repository at this point in the history
Load the mythfrontend .ts file in mythbackend to enable translation
in mythbackend's HTML server.  This uses the mythfrontend .ts files
because that is what mythtv-setup uses and the primary reason for
enabling translation in the backend is to translate the backend
setup webpages being developed.  The backend normally serves only
data, not presentation, so the backend should not normally be
executing tr() to translate messages for the user.  The HTML setup
pages are different.  We want the backend to automatically translate
.qsp and .qjs files before they are presented to the user.

This patch enables translation of the menu.qsp main menu in the HTML
setup webpages.  To enable translation in other .qsp and .qjs files,
the translatable text should be wrapped in <i18n> and </i18n> opening
and closing tags.  Only .qsp and .qjs are processed for translations,
so all .html and .js files needing translation must be renamed to
.qsp and .qjs respectively.

To rebuild the htmlstrings.h file, change to the mythtv/html directory
and run ./buildhtmlstrings.sh.  Once htmlstrings.h has been
regenerated, change to the mythtv/i18n directory and run the normal
lupdate command to pull in the strings from htmlstrings.h and allow
their translation.

Since mythtv-setup is already using the mythfrontend *.ts files for
translations, there should be no new requirements for files to be
installed on a backend server via packagers because the mythfrontend
*.ts files should already be installed on both frontends and backends.

The *.ts files have not been updated as part of this commit.  There
are some strings in htmlstrings.h which are already translated in the
existing *.ts files.  This commit can be tested by changing your
Language setting, restarting mythbackend, and looking in the HTML setup
menu at options like 'General' and 'Job Queue' which already exist in
the existing *.ts files.
  • Loading branch information
cpinkham committed Apr 26, 2011
1 parent 504189d commit ae4a014
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 31 deletions.
27 changes: 27 additions & 0 deletions mythtv/html/buildhtmlstrings.sh
@@ -0,0 +1,27 @@
#!/bin/sh

BASEDIR="."
OUTFILE="${BASEDIR}/htmlstrings.h"

echo "/*********************************************************/" > ${OUTFILE}
echo "/* This file is automatically generated by running the */" >> ${OUTFILE}
echo "/* buildhtmlstrings.sh script which parses translatable */" >> ${OUTFILE}
echo "/* strings from .qsp and .qjs files under the html */" >> ${OUTFILE}
echo "/* subdirectory using getTransStringsFromFile.pl. This */" >> ${OUTFILE}
echo "/* file should be regenerated before running lupdate in */" >> ${OUTFILE}
echo "/* the i18n directory to regenerate the i18n/*.ts files. */" >> ${OUTFILE}
echo "/*********************************************************/" >> ${OUTFILE}
echo >> ${OUTFILE}
echo "void html_strings_null() {" >> ${OUTFILE}

find ${BASEDIR}/ -type f | egrep "\.(qsp|qjs)$" | while read FILE
do
echo "Checking: ${FILE}"
${BASEDIR}/getTransStringsFromFile.pl ${BASEDIR}/${FILE} ${FILE} >> ${OUTFILE}
done

echo " QString()" >> ${OUTFILE}
echo "}" >> ${OUTFILE}

echo "================================================================="
cat ${OUTFILE}
47 changes: 47 additions & 0 deletions mythtv/html/getTransStringsFromFile.pl
@@ -0,0 +1,47 @@
#!/usr/bin/perl -w

if (!defined($ARGV[0])) {
print "ERROR: Usage: getTransStringsFromFile.pl FILENAME\n";
exit -1;
}

my $inFile = $ARGV[0];
my $baseFile = defined($ARGV[1]) ? $ARGV[1] : $inFile;
my %strings;
my $contents = "";
open( IN, "< $inFile" ) || die "Can not open $inFile: $!";
while( my $line = <IN> ) {
chomp($line);

$line =~ s/^\s*//;
$line =~ s/\s*$//;

$contents .= " ";
$contents .= $line;
}
close( IN );

my @lines = split('>', $contents);
foreach my $line ( @lines ) {
if ($line =~ /<\/i18n$/i) {
$line =~ s/<\/i18n$//;
$line =~ s/"/\\"/g;
$strings{$line} = 1;
}
}

@lines = split('\)', $contents);
foreach my $line ( @lines ) {
if ($line =~ /qsTr\(/i) {
$line =~ s/.*qsTr\(\s*["']//i;
$line =~ s/['"]$//;
$strings{$line} = 1;
}
}

if (scalar(keys %strings)) {
print " /* $baseFile */\n";
foreach my $string ( sort keys %strings ) {
print " QObject::tr(\"" . $string . "\"),\n";
}
}
44 changes: 44 additions & 0 deletions mythtv/html/htmlstrings.h
@@ -0,0 +1,44 @@
/*********************************************************/
/* This file is automatically generated by running the */
/* buildhtmlstrings.sh script which parses translatable */
/* strings from .qsp and .qjs files under the html */
/* subdirectory using getTransStringsFromFile.pl. This */
/* file should be regenerated before running lupdate in */
/* the i18n directory to regenerate the i18n/*.ts files. */
/*********************************************************/

void html_strings_null() {
/* ./menu.qsp */
QObject::tr("API"),
QObject::tr("Advanced Setup"),
QObject::tr("Backend Status"),
QObject::tr("Change Password"),
QObject::tr("Channel Editor"),
QObject::tr("Channel Service"),
QObject::tr("Content Service"),
QObject::tr("DVR Service"),
QObject::tr("Database"),
QObject::tr("Database Tools"),
QObject::tr("Expert/Dev Setup"),
QObject::tr("General"),
QObject::tr("GetRecorded() Example"),
QObject::tr("GetStorageGroups()"),
QObject::tr("Guide Data"),
QObject::tr("Guide Data Sources"),
QObject::tr("Guide Service"),
QObject::tr("Hardware Profile"),
QObject::tr("Information"),
QObject::tr("Job Queue"),
QObject::tr("Myth Service"),
QObject::tr("Overview"),
QObject::tr("Recording Devices"),
QObject::tr("Send a Message"),
QObject::tr("Server Side Scripting"),
QObject::tr("Setup"),
QObject::tr("Setup Wizard"),
QObject::tr("Storage Groups"),
QObject::tr("System Events"),
QObject::tr("Utilities"),
QObject::tr("WSDL Links"),
QString()
}
62 changes: 31 additions & 31 deletions mythtv/html/menu.qsp
Expand Up @@ -3,23 +3,23 @@
</div>
<div id="menu">
<ul class="menu collapsible">
<li><a href='#'>Setup</a>
<li><a href='#'><i18n>Setup</i18n></a>
<ul class="acitem collapsible">
<li><a href='#' onClick="javascript:clearContent(); loadEditWindow('/setup/wizard.html', '/setup/js/wizard.js')">Setup Wizard</a></li>
<li><a href='#'>Advanced Setup</a>
<li><a href='#' onClick="javascript:clearContent(); loadEditWindow('/setup/wizard.html', '/setup/js/wizard.js')"><i18n>Setup Wizard</i18n></a></li>
<li><a href='#'><i18n>Advanced Setup</i18n></a>
<ul class="acitem collapsible">
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('database')">Database</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('general')">General</a></li>
<li class="indent1"><a href='#'>Guide Data</a>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('database')"><i18n>Database</i18n></a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('general')"><i18n>General</i18n></a></li>
<li class="indent1"><a href='#'><i18n>Guide Data</i18n></a>
<ul class="acitem collapsible">
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('guidedatasources')">Guide Data Sources</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('channeleditor')">Channel Editor</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('guidedatasources')"><i18n>Guide Data Sources</i18n></a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('channeleditor')"><i18n>Channel Editor</i18n></a></li>
</ul>
</li>
<li class="indent1"><a href='#' onClick="javascript:loadContent('/misc/placeholder.html')">Recording Devices</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('storagegroups')">Storage Groups</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('jobqueue')">Job Queue</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('systemevents')">System Events</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadContent('/misc/placeholder.html')"><i18n>Recording Devices</i18n></a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('storagegroups')"><i18n>Storage Groups</i18n></a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('jobqueue')"><i18n>Job Queue</i18n></a></li>
<li class="indent1"><a href='#' onClick="javascript:loadSetupPage('systemevents')"><i18n>System Events</i18n></a></li>
</ul>
</li>
<%
Expand All @@ -32,44 +32,44 @@

if (devMode)
{
os.write("<li><a href='#' onClick=\"javascript:loadSetupContent('/setup/expert.html')\">Expert/Dev Setup</a></li>");
os.write("<li><a href='#' onClick=\"javascript:loadSetupContent('/setup/expert.html')\"><i18n>Expert/Dev Setup</i18n></a></li>");
}
%>
<li><a href='#' onClick="javascript:loadSetupPage('password')">Change Password</a></li>
<li><a href='#' onClick="javascript:loadSetupPage('password')"><i18n>Change Password</i18n></a></li>
</ul>
</li>
<li><a href='#'>Information</a>
<li><a href='#'><i18n>Information</i18n></a>
<ul class="acitem collapsible">
<li><a class='menuitem' href='#' onClick="javascript:loadContent('/Status/GetStatusHTML')">Backend Status</a></li>
<li><a class='menuitem' href='#' onClick="javascript:loadContent('/Status/GetStatusHTML')"><i18n>Backend Status</i18n></a></li>
</ul>
</li>
<li><a href='#'>Utilities</a>
<li><a href='#'><i18n>Utilities</i18n></a>
<ul class="acitem collapsible">
<li><a class='menuitem' href='#' onClick="javascript:loadMiscPage('messagetab')">Send a Message</a></li>
<li><a class='menuitem' href='#' onClick="javascript:loadMiscPage('databasetabs')">Database Tools</a></li>
<li><a class='menuitem' href='#' onClick="javascript:loadMiscPage('hardwareprofile')">Hardware Profile</a></li>
<li><a class='menuitem' href='#' onClick="javascript:loadMiscPage('messagetab')"><i18n>Send a Message</i18n></a></li>
<li><a class='menuitem' href='#' onClick="javascript:loadMiscPage('databasetabs')"><i18n>Database Tools</i18n></a></li>
<li><a class='menuitem' href='#' onClick="javascript:loadMiscPage('hardwareprofile')"><i18n>Hardware Profile</i18n></a></li>
</ul>
</li>
<li><hr></li>
<li><a href='#'>API</a>
<li><a href='#'><i18n>API</i18n></a>
<ul class="acitem collapsible">
<li><a href='#'>WSDL Links</a>
<li><a href='#'><i18n>WSDL Links</i18n></a>
<ul class="acitem">
<li class="indent1"><a href='/Myth/wsdl'>Myth Service</a></li>
<li class="indent1"><a href='/Guide/wsdl'>Guide Service</a></li>
<li class="indent1"><a href='/Dvr/wsdl'>DVR Service</a></li>
<li class="indent1"><a href='/Content/wsdl'>Content Service</a></li>
<li class="indent1"><a href='/Channel/wsdl'>Channel Service</a></li>
<li class="indent1"><a href='/Myth/wsdl'><i18n>Myth Service</i18n></a></li>
<li class="indent1"><a href='/Guide/wsdl'><i18n>Guide Service</i18n></a></li>
<li class="indent1"><a href='/Dvr/wsdl'><i18n>DVR Service</i18n></a></li>
<li class="indent1"><a href='/Content/wsdl'><i18n>Content Service</i18n></a></li>
<li class="indent1"><a href='/Channel/wsdl'><i18n>Channel Service</i18n></a></li>
</ul>
</li>
<li><a href='#'>Server Side Scripting</a>
<li><a href='#'><i18n>Server Side Scripting</i18n></a>
<ul class="acitem">
<li class="indent1"><a href='#' onClick="javascript:loadContent('/samples/serverside.qsp', '/samples/js/samples.js')">Overview</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadContent('/samples/recorded.qsp', '/samples/js/samples.js')">GetRecorded() Example</a></li>
<li class="indent1"><a href='#' onClick="javascript:loadContent('/samples/serverside.qsp', '/samples/js/samples.js')"><i18n>Overview</i18n></a></li>
<li class="indent1"><a href='#' onClick="javascript:loadContent('/samples/recorded.qsp', '/samples/js/samples.js')"><i18n>GetRecorded() Example</i18n></a></li>
<%
if (devMode)
{
os.write("<li class='indent1'><a href='#' onClick=\"javascript:loadContent('/samples/storagegroups.qsp', '/samples/js/samples.js')\">GetStorageGroups()</a></li>");
os.write("<li class='indent1'><a href='#' onClick=\"javascript:loadContent('/samples/storagegroups.qsp', '/samples/js/samples.js')\"><i18n>GetStorageGroups()</i18n></a></li>");
}
%>
</ul>
Expand Down
1 change: 1 addition & 0 deletions mythtv/i18n/translate.pro
Expand Up @@ -23,6 +23,7 @@ SOURCES += ../programs/mythshutdown/*.cpp
SOURCES += ../programs/mythjobqueue/*.cpp
SOURCES += ../programs/mythtvosd/*.cpp
SOURCES += ../themes/themestrings.h
SOURCES += ../html/htmlstrings.h

TRANSLATIONS = mythfrontend_bg.ts
TRANSLATIONS += mythfrontend_ca.ts
Expand Down
3 changes: 3 additions & 0 deletions mythtv/programs/mythbackend/main_helpers.cpp
Expand Up @@ -51,6 +51,7 @@
#include "mythsystemevent.h"
#include "main_helpers.h"
#include "backendcontext.h"
#include "mythtranslation.h"

#include "mediaserver.h"
#include "httpstatus.h"
Expand Down Expand Up @@ -672,6 +673,8 @@ int run_backend(const MythCommandLineParser &cmdline)
return GENERIC_EXIT_DB_OUTOFDATE;
}

MythTranslation::load("mythfrontend");

if (!ismaster)
{
int ret = connect_to_master();
Expand Down

0 comments on commit ae4a014

Please sign in to comment.