Skip to content

Commit

Permalink
Add support for Firefox for iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
flodolo committed Oct 5, 2015
1 parent a05a5eb commit 9868ea2
Show file tree
Hide file tree
Showing 14 changed files with 351 additions and 10 deletions.
6 changes: 5 additions & 1 deletion app/classes/Transvision/AnalyseStrings.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ public static function differences($tmx_source, $tmx_target, $repo, $ignored_str

if (Strings::startsWith($repo, 'gaia')) {
$patterns = [
'l10njs' => '/\{\{\s*([a-z0-9_]+)\s*\}\}/iu', // {{foobar2}}
'l10njs' => '/\{\{\s*([a-z0-9_]+)\s*\}\}/iu', // {{foobar2}}
];
} elseif ($repo == 'firefox_ios') {
$patterns = [
'ios' => '/(%(?:[0-9]+\$){0,1}@)/i', // %@, but also %1$@, %2$@, etc.
];
} else {
$patterns = [
Expand Down
12 changes: 8 additions & 4 deletions app/classes/Transvision/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ public static function getGaiaRepositories()
public static function getDesktopRepositories()
{
return array_diff(
array_diff(self::getRepositories(), ['mozilla_org']),
self::getRepositories(),
['mozilla_org', 'firefox_ios'],
self::getGaiaRepositories()
);
}
Expand Down Expand Up @@ -224,14 +225,17 @@ public static function getLocaleInContext($locale, $context)
'sr' => 'sr-Cyrl',
];

// Other contexts. At the moment, identical to Bugzilla list
$locale_mappings['other'] = $locale_mappings['bugzilla'];

// Use Gaia mapping for all Gaia repositories
if (Strings::startsWith($context, 'gaia')) {
$context = 'gaia';
}

// Firefox for iOS: no mapping
$locale_mappings['firefox_ios'] = [];

// For other contexts use the same as Bugzilla
$locale_mappings['other'] = $locale_mappings['bugzilla'];

// Fallback to 'other' if context doesn't exist in $locale_mappings
$context = array_key_exists($context, $locale_mappings)
? $context
Expand Down
5 changes: 5 additions & 0 deletions app/classes/Transvision/ShowResults.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@ public static function resultsTable($search_results, $recherche, $locale1, $loca
if ($search_options['repo'] == 'mozilla_org') {
$locale1_path = VersionControl::gitPath($locale1, $search_options['repo'], $key);
$locale2_path = VersionControl::gitPath($locale2, $search_options['repo'], $key);
} elseif ($search_options['repo'] == 'firefox_ios') {
$locale1_path = VersionControl::svnPath($locale1, $search_options['repo'], $key);
$locale2_path = VersionControl::svnPath($locale2, $search_options['repo'], $key);
} else {
$locale1_path = VersionControl::hgPath($locale1, $search_options['repo'], $key);
$locale2_path = VersionControl::hgPath($locale2, $search_options['repo'], $key);
Expand Down Expand Up @@ -332,6 +335,8 @@ public static function resultsTable($search_results, $recherche, $locale1, $loca
if (isset($search_options["extra_locale"])) {
if ($search_options['repo'] == 'mozilla_org') {
$locale3_path = VersionControl::gitPath($locale3, $search_options['repo'], $key);
} elseif ($search_options['repo'] == 'firefox_ios') {
$locale3_path = VersionControl::svnPath($locale3, $search_options['repo'], $key);
} else {
$locale3_path = VersionControl::hgPath($locale3, $search_options['repo'], $key);
}
Expand Down
7 changes: 5 additions & 2 deletions app/classes/Transvision/VersionControl.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ class VersionControl
public static function getVCS($repo)
{
$vcs = [
'hg' => [],
'git' => ['mozilla_org'],
'hg' => [],
'svn' => ['firefox_ios'],
];
$vcs['hg'] = array_merge(
Project::getDesktopRepositories(),
Expand Down Expand Up @@ -197,9 +198,11 @@ public static function svnPath($locale, $repo, $path)
if ($repo == 'mozilla_org') {
$file_path = 'projects/mozilla.com/trunk/locales/'
. $locale . '/' . self::extractFilePath($path);
} elseif ($repo == 'firefox_ios') {
$file_path = "projects/l10n-misc/trunk/firefox-ios/{$locale}/firefox-ios.xliff";
}

return 'http://viewvc.svn.mozilla.org/vc/'
return 'https://viewvc.svn.mozilla.org/vc/'
. $file_path . '?view=markup';
}

Expand Down
65 changes: 65 additions & 0 deletions app/classes/Transvision/Xliff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php
namespace Transvision;

/**
* Xliff class
*
* This class is used to manipulate translation files in XLIFF format
* used in Firefox for iOS.
*
* @package Transvision
*/
class Xliff
{
/**
*
* Loads strings from a .xliff file
*
* @param string $xliff_path Path to the .xliff to load
* @param string $project_name The project this string belongs to
*
* @return array Array of strings as [string_id => translation]
*/
public static function getStrings($xliff_path, $project_name)
{
$strings = [];
if ($xml = simplexml_load_file($xliff_path)) {
$namespaces = $xml->getDocNamespaces();
$xml->registerXPathNamespace('x', $namespaces['']);
/* Get all trans-units, which include both reference (source) and
/* translation (target)
*/
$trans_units = $xml->xpath('//x:trans-unit');
foreach ($trans_units as $trans_unit) {
/* File's name is 2 levels above in the hierarchy, stored as
* 'original' attribute of the <file> element.
*/
$file_node = $trans_unit->xpath('../..');
$file_name = $file_node[0]['original'];

$string_id = self::generateStringID($project_name, $file_name, $trans_unit['id']);
$translation = str_replace("'", "\\'", $trans_unit->target);

$strings[$string_id] = $translation;
}
}

return $strings;
}

/**
* Generate a unique id for a string to store in Transvision.
* String ID can be identical to the source string in iOS, so it's more
* reliable to generate a unique ID from it.
*
* @param string $project_name The project this string belongs to
* @param string $file_name 'original' attribute of the <file> element
* @param string $string_id 'id' attribute of the <trans-unit> element
*
* @return string unique ID such as firefox_ios/Client/Intro.strings:1cd1dc4e
*/
public static function generateStringID($project_name, $file_name, $string_id)
{
return "{$project_name}/{$file_name}:" . hash('crc32', $string_id);
}
}
4 changes: 4 additions & 0 deletions app/scripts/bash_variables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ done
mozilla_org=$local_git/mozilla_org/
folders+=( $mozilla_org )

# Firefox for iOS (XLIFF)
firefox_ios=$local_svn/firefox_ios/
folders+=( $firefox_ios )

# l20n test repo
l20n_test=$local_git/L20N_TEST
l20n_test_locales=${path_sources}/l20n_test.txt
Expand Down
17 changes: 16 additions & 1 deletion app/scripts/glossaire.sh
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,21 @@ function updateFromGitHub() {
fi
}

function updateFirefoxiOS() {
if $checkrepo
then
cd $firefox_ios
echogreen "Update subversion repository"
svn up
fi
if $createTMX
then
echogreen "Extract strings for Firefox for iOS"
cd $install
nice -20 app/scripts/tmx_xliff firefox_ios
fi
}

# Update repos without branches first (their TMX is created in updateStandardRepo)
updateNoBranchRepo "chatzilla"
updateNoBranchRepo "venkman"
Expand All @@ -296,8 +311,8 @@ do
updateGaiaRepo ${gaia_version}
done

# mozilla.org has its own extraction script
updateFromGitHub
updateFirefoxiOS

# Generate productization data
cd $install
Expand Down
8 changes: 8 additions & 0 deletions app/scripts/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,14 @@ then
git clone https://github.com/mozilla-l10n/www.mozilla.org .
fi

echogreen "Firefox for iOS repo being checked out from subversion"
cd $firefox_ios
if [ ! -d $firefox_ios/.svn ]
then
echogreen "Checking out Firefox for iOS repo"
svn co https://svn.mozilla.org/projects/l10n-misc/trunk/firefox-ios/ .
fi

# We now deal with L20n test repo as a specific case
echogreen "L20n test repo initialization"
cd $l20n_test
Expand Down
57 changes: 57 additions & 0 deletions app/scripts/tmx_xliff
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env php
<?php
namespace Transvision;

// Script should not be called from the Web
if (php_sapi_name() != 'cli') {
die("This command can only be used in CLI mode.\n");
}

if (count($argv) < 2) {
die("This command needs more parameters, please check tmx_xliff --help.\n");
}
if (isset($argv[1])) {
if (in_array($argv[1], ['-h', '--help'])) {
$command_help = "tmx_xliff - Create TMX from XLIFF file\n" .
"Usage: tmx_xliff [project_name]\n\n" .
"Example: tmx_xliff firefox_ios\n";
die($command_help);
}
}

include __DIR__ . '/../inc/init.php';

$project_name = $argv[1];

$supported_projects = [
'firefox_ios' => [
'file_name' => 'firefox-ios.xliff',
'base_path' => SVN . 'firefox_ios',
],
];

if (! isset($supported_projects[$project_name])) {
die("Unknown project: {$project_name}.\n");
}
error_log('Extraction of strings from XLIFF file');

$base_path = $supported_projects[$project_name]['base_path'];
foreach (Files::getFilenamesInFolder($base_path, ['templates', 'README']) as $locale) {
$out_translation = '';
$total_strings = 0;

$xliff_path = "{$base_path}/{$locale}/{$supported_projects[$project_name]['file_name']}";
if (file_exists($xliff_path)) {
$strings = Xliff::getStrings($xliff_path, $project_name);
$total_strings = count($strings);
foreach ($strings as $string_id => $translation) {
$out_translation .= "'{$string_id}' => '{$translation}', \n";
}
} else {
error_log("{$locale}: file is missing");
}
$out_translation = "<?php\n\$tmx = [\n" . $out_translation . "];\n";

Files::fileForceContents(TMX . "{$locale}/cache_{$locale}_{$project_name}.php", $out_translation);
error_log("{$locale}: {$total_strings} strings");
}
5 changes: 5 additions & 0 deletions app/views/results_entities.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
if ($check['repo'] == 'mozilla_org') {
$path_locale1 = VersionControl::gitPath($source_locale, $check['repo'], $entity);
$path_locale2 = VersionControl::gitPath($locale, $check['repo'], $entity);
} elseif ($check['repo'] == 'firefox_ios') {
$path_locale1 = VersionControl::svnPath($source_locale, $check['repo'], $entity);
$path_locale2 = VersionControl::svnPath($locale, $check['repo'], $entity);
} else {
$path_locale1 = VersionControl::hgPath($source_locale, $check['repo'], $entity);
$path_locale2 = VersionControl::hgPath($locale, $check['repo'], $entity);
Expand All @@ -42,6 +45,8 @@

if ($check['repo'] == 'mozilla_org') {
$path_locale3 = VersionControl::gitPath($locale2, $check['repo'], $entity);
} elseif ($check['repo'] == 'firefox_ios') {
$path_locale3 = VersionControl::svnPath($locale2, $check['repo'], $entity);
} else {
$path_locale3 = VersionControl::hgPath($locale2, $check['repo'], $entity);
}
Expand Down
79 changes: 79 additions & 0 deletions tests/testfiles/xliff/firefox-ios.xliff
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?xml version='1.0' encoding='UTF-8'?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="Client/BookmarkPanel.strings" source-language="en" datatype="plaintext" target-language="it">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="7.0" build-num="7A220"/>
</header>
<body>
<trans-unit id="Delete">
<source>Delete</source>
<target>Elimina</target>
<note>Action button for deleting bookmarks in the bookmarks panel.</note>
</trans-unit>
<trans-unit id="Desktop Bookmarks">
<source>Desktop Bookmarks</source>
<target>Segnalibri pc desktop</target>
<note>The folder name for the virtual folder that contains all desktop bookmarks.</note>
</trans-unit>
</body>
</file>
<file original="Client/ClearPrivateData.strings" source-language="en" datatype="plaintext" target-language="it">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="7.0" build-num="7A220"/>
</header>
<body>
<trans-unit id="Are you sure you want to clear all of your data? This will also close all open tabs.">
<source>Are you sure you want to clear all of your data? This will also close all open tabs.</source>
<target>Eliminare tutti i dati? Verranno anche chiuse tutte le schede aperte.</target>
<note>Message shown in the dialog prompting users if they want to clear everything</note>
</trans-unit>
<trans-unit id="Browsing History">
<source>Browsing History</source>
<target>Cronologia di navigazione</target>
<note>Settings item for clearing browsing history</note>
</trans-unit>
<trans-unit id="Cache">
<source>Cache</source>
<target>Cache</target>
<note>Settings item for clearing the cache</note>
</trans-unit>
<trans-unit id="Cancel">
<source>Cancel</source>
<target>Annulla</target>
<note>Used as a button label in the dialog to cancel clear private data dialog</note>
</trans-unit>
<trans-unit id="Clear">
<source>Clear</source>
<target>Elimina</target>
<note>Used as a button label in the dialog to Clear private data dialog</note>
</trans-unit>
<trans-unit id="Clear Everything">
<source>Clear Everything</source>
<target>Eliminazione dati</target>
<note>Title of the Clear private data dialog.</note>
</trans-unit>
<trans-unit id="Clear Private Data">
<source>Clear Private Data</source>
<target>Elimina dati personali</target>
<note>Button in settings that clears private data for the selected items.
Navigation title in settings.</note>
</trans-unit>
<trans-unit id="Cookies">
<source>Cookies</source>
<target>Cookie</target>
<note>Settings item for clearing cookies</note>
</trans-unit>
<trans-unit id="Offline Website Data">
<source>Offline Website Data</source>
<target>Dati non in linea dei siti web</target>
<note>Settings item for clearing website data</note>
</trans-unit>
<trans-unit id="Saved Logins">
<source>Saved Logins</source>
<target>Accessi salvati</target>
<note>Settings item for clearing passwords and login data</note>
</trans-unit>
</body>
</file>
</xliff>

24 changes: 24 additions & 0 deletions tests/units/Transvision/AnalyseStrings.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,30 @@ public function differencesDP()
[],
[],
],
[
// mispelled variable
['ios:foobar1' => 'Introductory slide %1$@ of %2$@'],
['ios:foobar1' => 'Introduzione (passaggio %1$@ di %$@)'],
'firefox_ios',
[],
['ios:foobar1'],
],
[
// missing variable
['ios:foobar2' => 'Do you want to save the password on %@?'],
['ios:foobar2' => 'Salvare la password?'],
'firefox_ios',
[],
['ios:foobar2'],
],
[
// changed order, not an error
['ios:foobar3' => 'Introductory slide %1$@ of %2$@'],
['ios:foobar3' => 'Introduzione (passaggio %2$@ di %1$@)'],
'firefox_ios',
[],
[],
],
];
}

Expand Down
Loading

0 comments on commit 9868ea2

Please sign in to comment.