Diff
Modified: trunk/Source/WebCore/ChangeLog (156190 => 156191)
--- trunk/Source/WebCore/ChangeLog 2013-09-20 19:56:33 UTC (rev 156190)
+++ trunk/Source/WebCore/ChangeLog 2013-09-20 20:13:11 UTC (rev 156191)
@@ -1,3 +1,15 @@
+2013-09-20 Dan Bernstein <[email protected]>
+
+ Make extract-localizable-strings available to WebCore clients
+ https://bugs.webkit.org/show_bug.cgi?id=121699
+
+ Reviewed by Darin Adler.
+
+ * WebCore.xcodeproj/project.pbxproj: Added a Scripts group with a reference to
+ extract-localizable-strings.pl. Added a Copy Scripts build phase to the WebCore target that
+ copies the script into PrivateHeaders/Scripts in the framework.
+ * extract-localizable-strings.pl: Copied from Tools/Scripts/extract-localizable-strings.
+
2013-09-20 Antti Koivisto <[email protected]>
Move layer hierarchy functions from RenderObject to RenderElement
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (156190 => 156191)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-09-20 19:56:33 UTC (rev 156190)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-09-20 20:13:11 UTC (rev 156191)
@@ -1082,6 +1082,7 @@
3390CA560FFC157B00921962 /* NotificationCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3390CA520FFC157B00921962 /* NotificationCenter.h */; };
339B5B63131DAA3200F48D02 /* CookiesStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 339B5B62131DAA3200F48D02 /* CookiesStrategy.h */; settings = {ATTRIBUTES = (Private, ); }; };
33D0212D131DB37B004091A8 /* CookieStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = E13F01EA1270E10D00DFBA71 /* CookieStorage.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 3717D7E817ECC591003C276D /* extract-localizable-strings.pl in Copy Scripts */ = {isa = PBXBuildFile; fileRef = 3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */; };
371941961566B37200A276D8 /* WebCoreNSCellExtras.m in Sources */ = {isa = PBXBuildFile; fileRef = 371941941566B37200A276D8 /* WebCoreNSCellExtras.m */; };
371941971566B37200A276D8 /* WebCoreNSCellExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 371941951566B37200A276D8 /* WebCoreNSCellExtras.h */; };
371A67CB11C6C7DB00047B8B /* HyphenationCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 371A67CA11C6C7DB00047B8B /* HyphenationCF.cpp */; };
@@ -6397,6 +6398,17 @@
name = "Copy Generated Headers";
runOnlyForDeploymentPostprocessing = 0;
};
+ 3717D7E717ECC573003C276D /* Copy Scripts */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = PrivateHeaders/Scripts;
+ dstSubfolderSpec = 1;
+ files = (
+ 3717D7E817ECC591003C276D /* extract-localizable-strings.pl in Copy Scripts */,
+ );
+ name = "Copy Scripts";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
CD0DBF001422765700280263 /* Copy Audio Resources */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -7577,6 +7589,7 @@
3390CA520FFC157B00921962 /* NotificationCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotificationCenter.h; path = Modules/notifications/NotificationCenter.h; sourceTree = "<group>"; };
3390CA530FFC157B00921962 /* NotificationCenter.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = NotificationCenter.idl; path = Modules/notifications/NotificationCenter.idl; sourceTree = "<group>"; };
339B5B62131DAA3200F48D02 /* CookiesStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CookiesStrategy.h; sourceTree = "<group>"; };
+ 3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */ = {isa = PBXFileReference; lastKnownFileType = text.script.perl; path = "extract-localizable-strings.pl"; sourceTree = "<group>"; };
371941941566B37200A276D8 /* WebCoreNSCellExtras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebCoreNSCellExtras.m; sourceTree = "<group>"; };
371941951566B37200A276D8 /* WebCoreNSCellExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreNSCellExtras.h; sourceTree = "<group>"; };
371A67CA11C6C7DB00047B8B /* HyphenationCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HyphenationCF.cpp; sourceTree = "<group>"; };
@@ -13567,6 +13580,7 @@
E1F0424309839389006694EA /* xml */,
656580EC09D12B20000E61D7 /* Derived Sources */,
089C1665FE841158C02AAC07 /* Resources */,
+ 3717D7E417ECC36C003C276D /* Scripts */,
0867D69AFE84028FC02AAC07 /* Frameworks */,
034768DFFF38A50411DB9C8B /* Products */,
1CDD44660BA9C80000F90147 /* Configurations */,
@@ -14400,6 +14414,14 @@
name = Notifications;
sourceTree = "<group>";
};
+ 3717D7E417ECC36C003C276D /* Scripts */ = {
+ isa = PBXGroup;
+ children = (
+ 3717D7E517ECC3A6003C276D /* extract-localizable-strings.pl */,
+ );
+ name = Scripts;
+ sourceTree = "<group>";
+ };
37DDCD9F1384501C0008B793 /* mhtml */ = {
isa = PBXGroup;
children = (
@@ -24742,6 +24764,7 @@
93F198A608245E59001E9ABC /* Headers */,
1C11CCB40AA6093700DADB20 /* Copy Generated Headers */,
5D87BC0711E43BDE00702B6F /* Copy Forwarding and ICU Headers */,
+ 3717D7E717ECC573003C276D /* Copy Scripts */,
93F199FD08245E59001E9ABC /* Resources */,
CD0DBF001422765700280263 /* Copy Audio Resources */,
1C81BA330E97357C00266E07 /* Copy Inspector Resources */,
Copied: trunk/Source/WebCore/extract-localizable-strings.pl (from rev 156190, trunk/Tools/Scripts/extract-localizable-strings) (0 => 156191)
--- trunk/Source/WebCore/extract-localizable-strings.pl (rev 0)
+++ trunk/Source/WebCore/extract-localizable-strings.pl 2013-09-20 20:13:11 UTC (rev 156191)
@@ -0,0 +1,447 @@
+#!/usr/bin/perl -w
+
+# Copyright (C) 2006, 2007, 2009, 2010, 2013 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This script is like the genstrings tool (minus most of the options) with these differences.
+#
+# 1) It uses the names UI_STRING and UI_STRING_WITH_KEY for the macros, rather than the macros
+# from NSBundle.h, and doesn't support tables (although they would be easy to add).
+# 2) It supports UTF-8 in key strings (and hence uses "" strings rather than @"" strings;
+# @"" strings only reliably support ASCII since they are decoded based on the system encoding
+# at runtime, so give different results on US and Japanese systems for example).
+# 3) It looks for strings that are not marked for localization, using both macro names that are
+# known to be used for debugging in Intrigue source code and an exceptions file.
+# 4) It finds the files to work on rather than taking them as parameters, and also uses a
+# hardcoded location for both the output file and the exceptions file.
+# It would have been nice to use the project to find the source files, but it's too hard to
+# locate source files after parsing a .pbxproj file.
+
+# The exceptions file has a list of strings in quotes, filenames, and filename/string pairs separated by :.
+
+use strict;
+use Getopt::Long;
+no warnings 'deprecated';
+
+sub UnescapeHexSequence($);
+
+my %isDebugMacro = ( ASSERT_WITH_MESSAGE => 1, LOG_ERROR => 1, ERROR => 1, NSURL_ERROR => 1, FATAL => 1, LOG => 1, LOG_WARNING => 1, UI_STRING_LOCALIZE_LATER => 1, UI_STRING_LOCALIZE_LATER_KEY => 1, LPCTSTR_UI_STRING_LOCALIZE_LATER => 1, UNLOCALIZED_STRING => 1, UNLOCALIZED_LPCTSTR => 1, dprintf => 1, NSException => 1, NSLog => 1, printf => 1 );
+
+my $verify;
+my $exceptionsFile;
+my @directoriesToSkip = ();
+
+my %options = (
+ 'verify' => \$verify,
+ 'exceptions=s' => \$exceptionsFile,
+ 'skip=s' => \@directoriesToSkip,
+);
+
+GetOptions(%options);
+
+@ARGV >= 2 or die "Usage: extract-localizable-strings [--verify] [--exceptions <exceptions file>] <file to update> [--skip directory | directory]...\nDid you mean to run update-webkit-localizable-strings instead?\n";
+
+-f $exceptionsFile or die "Couldn't find exceptions file $exceptionsFile\n" unless !defined $exceptionsFile;
+
+my $fileToUpdate = shift @ARGV;
+-f $fileToUpdate or die "Couldn't find file to update $fileToUpdate\n";
+
+my $warnAboutUnlocalizedStrings = defined $exceptionsFile;
+
+my @directories = ();
+if (@ARGV < 1) {
+ push(@directories, ".");
+} else {
+ for my $dir (@ARGV) {
+ push @directories, $dir;
+ }
+}
+
+my $sawError = 0;
+
+my $localizedCount = 0;
+my $keyCollisionCount = 0;
+my $notLocalizedCount = 0;
+my $NSLocalizeCount = 0;
+
+my %exception;
+my %usedException;
+
+if (defined $exceptionsFile && open EXCEPTIONS, $exceptionsFile) {
+ while (<EXCEPTIONS>) {
+ chomp;
+ if (/^"([^\\"]|\\.)*"$/ or /^[-_\/\w\s.]+.(h|m|mm|c|cpp)$/ or /^[-_\/\w\s.]+.(h|m|mm|c|cpp):"([^\\"]|\\.)*"$/) {
+ if ($exception{$_}) {
+ print "$exceptionsFile:$.: warning: exception for $_ appears twice\n";
+ print "$exceptionsFile:$exception{$_}: warning: first appearance\n";
+ } else {
+ $exception{$_} = $.;
+ }
+ } else {
+ print "$exceptionsFile:$.: warning: syntax error\n";
+ }
+ }
+ close EXCEPTIONS;
+}
+
+my $quotedDirectoriesString = '"' . join('" "', @directories) . '"';
+for my $dir (@directoriesToSkip) {
+ $quotedDirectoriesString .= ' -path "' . $dir . '" -prune -o';
+}
+
+my @files = ( split "\n", `find $quotedDirectoriesString \\( -name "*.h" -o -name "*.m" -o -name "*.mm" -o -name "*.c" -o -name "*.cpp" \\)` );
+
+for my $file (sort @files) {
+ next if $file =~ /\/\w+LocalizableStrings\w*\.h$/ || $file =~ /\/LocalizedStrings\.h$/;
+
+ $file =~ s-^./--;
+
+ open SOURCE, $file or die "can't open $file\n";
+
+ my $inComment = 0;
+
+ my $expected = "";
+ my $macroLine;
+ my $macro;
+ my $UIString;
+ my $key;
+ my $comment;
+
+ my $string;
+ my $stringLine;
+ my $nestingLevel;
+
+ my $previousToken = "";
+
+ while (<SOURCE>) {
+ chomp;
+
+ # Handle continued multi-line comment.
+ if ($inComment) {
+ next unless s-.*\*/--;
+ $inComment = 0;
+ }
+
+ next unless defined $nestingLevel or /(\"|\/\*)/;
+
+ # Handle all the tokens in the line.
+ while (s-^\s*([#\w]+|/\*|//|[^#\w/'"()\[\],]+|.)--) {
+ my $token = $1;
+
+ if ($token eq "\"") {
+ if ($expected and $expected ne "a quoted string") {
+ print "$file:$.: found a quoted string but expected $expected\n";
+ $sawError = 1;
+ $expected = "";
+ }
+ if (s-^(([^\\$token]|\\.)*?)$token--) {
+ if (!defined $string) {
+ $stringLine = $.;
+ $string = $1;
+ } else {
+ $string .= $1;
+ }
+ } else {
+ print "$file:$.: mismatched quotes\n";
+ $sawError = 1;
+ $_ = "";
+ }
+ next;
+ }
+
+ if (defined $string) {
+handleString:
+ if ($expected) {
+ if (!defined $UIString) {
+ # FIXME: Validate UTF-8 here?
+ $UIString = $string;
+ $expected = ",";
+ } elsif (($macro =~ /(WEB_)?UI_STRING_KEY(_INTERNAL)?$/) and !defined $key) {
+ # FIXME: Validate UTF-8 here?
+ $key = $string;
+ $expected = ",";
+ } elsif (!defined $comment) {
+ # FIXME: Validate UTF-8 here?
+ $comment = $string;
+ $expected = ")";
+ }
+ } else {
+ if (defined $nestingLevel) {
+ # In a debug macro, no need to localize.
+ } elsif ($previousToken eq "#include" or $previousToken eq "#import") {
+ # File name, no need to localize.
+ } elsif ($previousToken eq "extern" and $string eq "C") {
+ # extern "C", no need to localize.
+ } elsif ($string eq "") {
+ # Empty string can sometimes be localized, but we need not complain if not.
+ } elsif ($exception{$file}) {
+ $usedException{$file} = 1;
+ } elsif ($exception{"\"$string\""}) {
+ $usedException{"\"$string\""} = 1;
+ } elsif ($exception{"$file:\"$string\""}) {
+ $usedException{"$file:\"$string\""} = 1;
+ } else {
+ print "$file:$stringLine: warning: \"$string\" is not marked for localization\n" if $warnAboutUnlocalizedStrings;
+ $notLocalizedCount++;
+ }
+ }
+ $string = undef;
+ last if !defined $token;
+ }
+
+ $previousToken = $token;
+
+ if ($token =~ /^NSLocalized/ && $token !~ /NSLocalizedDescriptionKey/ && $token !~ /NSLocalizedStringFromTableInBundle/ && $token !~ /NSLocalizedFileSizeDescription/ && $token !~ /NSLocalizedDescriptionKey/ && $token !~ /NSLocalizedRecoverySuggestionErrorKey/) {
+ print "$file:$.: found a use of an NSLocalized macro ($token); not supported\n";
+ $nestingLevel = 0 if !defined $nestingLevel;
+ $sawError = 1;
+ $NSLocalizeCount++;
+ } elsif ($token eq "/*") {
+ if (!s-^.*?\*/--) {
+ $_ = ""; # If the comment doesn't end, discard the result of the line and set flag
+ $inComment = 1;
+ }
+ } elsif ($token eq "//") {
+ $_ = ""; # Discard the rest of the line
+ } elsif ($token eq "'") {
+ if (!s-([^\\]|\\.)'--) { #' <-- that single quote makes the Project Builder editor less confused
+ print "$file:$.: mismatched single quote\n";
+ $sawError = 1;
+ $_ = "";
+ }
+ } else {
+ if ($expected and $expected ne $token) {
+ print "$file:$.: found $token but expected $expected\n";
+ $sawError = 1;
+ $expected = "";
+ }
+ if ($token =~ /(WEB_)?UI_STRING(_KEY)?(_INTERNAL)?$/) {
+ $expected = "(";
+ $macro = $token;
+ $UIString = undef;
+ $key = undef;
+ $comment = undef;
+ $macroLine = $.;
+ } elsif ($token eq "(" or $token eq "[") {
+ ++$nestingLevel if defined $nestingLevel;
+ $expected = "a quoted string" if $expected;
+ } elsif ($token eq ",") {
+ $expected = "a quoted string" if $expected;
+ } elsif ($token eq ")" or $token eq "]") {
+ $nestingLevel = undef if defined $nestingLevel && !--$nestingLevel;
+ if ($expected) {
+ $key = $UIString if !defined $key;
+ HandleUIString($UIString, $key, $comment, $file, $macroLine);
+ $macro = "";
+ $expected = "";
+ $localizedCount++;
+ }
+ } elsif ($isDebugMacro{$token}) {
+ $nestingLevel = 0 if !defined $nestingLevel;
+ }
+ }
+ }
+
+ }
+
+ goto handleString if defined $string;
+
+ if ($expected) {
+ print "$file: reached end of file but expected $expected\n";
+ $sawError = 1;
+ }
+
+ close SOURCE;
+}
+
+# Unescapes C language hexadecimal escape sequences.
+sub UnescapeHexSequence($)
+{
+ my ($originalStr) = @_;
+
+ my $escapedStr = $originalStr;
+ my $unescapedStr = "";
+
+ for (;;) {
+ if ($escapedStr =~ s-^\\x([[:xdigit:]]+)--) {
+ if (256 <= hex($1)) {
+ print "Hexadecimal escape sequence out of range: \\x$1\n";
+ return undef;
+ }
+ $unescapedStr .= pack("H*", $1);
+ } elsif ($escapedStr =~ s-^(.)--) {
+ $unescapedStr .= $1;
+ } else {
+ return $unescapedStr;
+ }
+ }
+}
+
+my %stringByKey;
+my %commentByKey;
+my %fileByKey;
+my %lineByKey;
+
+sub HandleUIString
+{
+ my ($string, $key, $comment, $file, $line) = @_;
+
+ my $bad = 0;
+ $string = UnescapeHexSequence($string);
+ if (!defined($string)) {
+ print "$file:$line: string has an illegal hexadecimal escape sequence\n";
+ $bad = 1;
+ }
+ $key = UnescapeHexSequence($key);
+ if (!defined($key)) {
+ print "$file:$line: key has an illegal hexadecimal escape sequence\n";
+ $bad = 1;
+ }
+ $comment = UnescapeHexSequence($comment);
+ if (!defined($comment)) {
+ print "$file:$line: comment has an illegal hexadecimal escape sequence\n";
+ $bad = 1;
+ }
+ if (grep { $_ == 0xFFFD } unpack "U*", $string) {
+ print "$file:$line: string for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n";
+ $bad = 1;
+ }
+ if ($string ne $key && grep { $_ == 0xFFFD } unpack "U*", $key) {
+ print "$file:$line: key has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n";
+ $bad = 1;
+ }
+ if (grep { $_ == 0xFFFD } unpack "U*", $comment) {
+ print "$file:$line: comment for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n";
+ $bad = 1;
+ }
+ if ($bad) {
+ $sawError = 1;
+ return;
+ }
+
+ if ($stringByKey{$key} && $stringByKey{$key} ne $string) {
+ print "$file:$line: warning: encountered the same key, \"$key\", twice, with different strings\n";
+ print "$fileByKey{$key}:$lineByKey{$key}: warning: previous occurrence\n";
+ $keyCollisionCount++;
+ return;
+ }
+ if ($commentByKey{$key} && $commentByKey{$key} ne $comment) {
+ print "$file:$line: warning: encountered the same key, \"$key\", twice, with different comments\n";
+ print "$fileByKey{$key}:$lineByKey{$key}: warning: previous occurrence\n";
+ $keyCollisionCount++;
+ return;
+ }
+
+ $fileByKey{$key} = $file;
+ $lineByKey{$key} = $line;
+ $stringByKey{$key} = $string;
+ $commentByKey{$key} = $comment;
+}
+
+print "\n" if $sawError || $notLocalizedCount || $NSLocalizeCount;
+
+my @unusedExceptions = sort grep { !$usedException{$_} } keys %exception;
+if (@unusedExceptions) {
+ for my $unused (@unusedExceptions) {
+ print "$exceptionsFile:$exception{$unused}: warning: exception $unused not used\n";
+ }
+ print "\n";
+}
+
+print "$localizedCount localizable strings\n" if $localizedCount;
+print "$keyCollisionCount key collisions\n" if $keyCollisionCount;
+print "$notLocalizedCount strings not marked for localization\n" if $notLocalizedCount;
+print "$NSLocalizeCount uses of NSLocalize\n" if $NSLocalizeCount;
+print scalar(@unusedExceptions), " unused exceptions\n" if @unusedExceptions;
+
+if ($sawError) {
+ print "\nErrors encountered. Exiting without writing to $fileToUpdate.\n";
+ exit 1;
+}
+
+my $localizedStrings = "";
+
+for my $key (sort keys %commentByKey) {
+ $localizedStrings .= "/* $commentByKey{$key} */\n\"$key\" = \"$stringByKey{$key}\";\n\n";
+}
+
+if (-e "$fileToUpdate") {
+ if (!$verify) {
+ # Write out the strings file as UTF-8
+ open STRINGS, ">", "$fileToUpdate" or die;
+ print STRINGS $localizedStrings;
+ close STRINGS;
+ } else {
+ open STRINGS, $fileToUpdate or die;
+
+ my $lastComment;
+ my $line;
+
+ while (<STRINGS>) {
+ chomp;
+
+ next if (/^\s*$/);
+
+ if (/^\/\* (.*) \*\/$/) {
+ $lastComment = $1;
+ } elsif (/^"((?:[^\\]|\\[^"])*)"\s*=\s*"((?:[^\\]|\\[^"])*)";$/) #
+ {
+ my $string = delete $stringByKey{$1};
+ if (!defined $string) {
+ print "$fileToUpdate:$.: unused key \"$1\"\n";
+ $sawError = 1;
+ } else {
+ if (!($string eq $2)) {
+ print "$fileToUpdate:$.: unexpected value \"$2\" for key \"$1\"\n";
+ print "$fileByKey{$1}:$lineByKey{$1}: expected value \"$string\" defined here\n";
+ $sawError = 1;
+ }
+ if (!($lastComment eq $commentByKey{$1})) {
+ print "$fileToUpdate:$.: unexpected comment /* $lastComment */ for key \"$1\"\n";
+ print "$fileByKey{$1}:$lineByKey{$1}: expected comment /* $commentByKey{$1} */ defined here\n";
+ $sawError = 1;
+ }
+ }
+ } else {
+ print "$fileToUpdate:$.: line with unexpected format: $_\n";
+ $sawError = 1;
+ }
+ }
+
+ for my $missing (keys %stringByKey) {
+ print "$fileByKey{$missing}:$lineByKey{$missing}: missing key \"$missing\"\n";
+ $sawError = 1;
+ }
+
+ if ($sawError) {
+ print "\n$fileToUpdate:0: file is not up to date.\n";
+ exit 1;
+ }
+ }
+} else {
+ print "error: $fileToUpdate does not exist\n";
+ exit 1;
+}
Modified: trunk/Tools/ChangeLog (156190 => 156191)
--- trunk/Tools/ChangeLog 2013-09-20 19:56:33 UTC (rev 156190)
+++ trunk/Tools/ChangeLog 2013-09-20 20:13:11 UTC (rev 156191)
@@ -1,3 +1,17 @@
+2013-09-20 Dan Bernstein <[email protected]>
+
+ Make extract-localizable-strings available to WebCore clients
+ https://bugs.webkit.org/show_bug.cgi?id=121699
+
+ Reviewed by Darin Adler.
+
+ * Scripts/extract-localizable-strings: Copied to
+ Soure/WebCore/extract-localizaebl-strings.pl, and changed this into a shell script that
+ executes the script from its new location. This is a temporary measure until certain code
+ that is external to WebKit is adapted to the new location.
+ * Scripts/update-webkit-localizable-strings: Changed to call extract-localizable-strings.pl
+ from its new location.
+
2013-09-20 Patrick Gansterer <[email protected]>
Nuke remaining VS2005 tools from the tree.
Modified: trunk/Tools/Scripts/extract-localizable-strings (156190 => 156191)
--- trunk/Tools/Scripts/extract-localizable-strings 2013-09-20 19:56:33 UTC (rev 156190)
+++ trunk/Tools/Scripts/extract-localizable-strings 2013-09-20 20:13:11 UTC (rev 156191)
@@ -1,447 +1,3 @@
-#!/usr/bin/perl -w
+#!/bin/sh
-# Copyright (C) 2006, 2007, 2009, 2010, 2013 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
-# its contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# This script is like the genstrings tool (minus most of the options) with these differences.
-#
-# 1) It uses the names UI_STRING and UI_STRING_WITH_KEY for the macros, rather than the macros
-# from NSBundle.h, and doesn't support tables (although they would be easy to add).
-# 2) It supports UTF-8 in key strings (and hence uses "" strings rather than @"" strings;
-# @"" strings only reliably support ASCII since they are decoded based on the system encoding
-# at runtime, so give different results on US and Japanese systems for example).
-# 3) It looks for strings that are not marked for localization, using both macro names that are
-# known to be used for debugging in Intrigue source code and an exceptions file.
-# 4) It finds the files to work on rather than taking them as parameters, and also uses a
-# hardcoded location for both the output file and the exceptions file.
-# It would have been nice to use the project to find the source files, but it's too hard to
-# locate source files after parsing a .pbxproj file.
-
-# The exceptions file has a list of strings in quotes, filenames, and filename/string pairs separated by :.
-
-use strict;
-use Getopt::Long;
-no warnings 'deprecated';
-
-sub UnescapeHexSequence($);
-
-my %isDebugMacro = ( ASSERT_WITH_MESSAGE => 1, LOG_ERROR => 1, ERROR => 1, NSURL_ERROR => 1, FATAL => 1, LOG => 1, LOG_WARNING => 1, UI_STRING_LOCALIZE_LATER => 1, UI_STRING_LOCALIZE_LATER_KEY => 1, LPCTSTR_UI_STRING_LOCALIZE_LATER => 1, UNLOCALIZED_STRING => 1, UNLOCALIZED_LPCTSTR => 1, dprintf => 1, NSException => 1, NSLog => 1, printf => 1 );
-
-my $verify;
-my $exceptionsFile;
-my @directoriesToSkip = ();
-
-my %options = (
- 'verify' => \$verify,
- 'exceptions=s' => \$exceptionsFile,
- 'skip=s' => \@directoriesToSkip,
-);
-
-GetOptions(%options);
-
-@ARGV >= 2 or die "Usage: extract-localizable-strings [--verify] [--exceptions <exceptions file>] <file to update> [--skip directory | directory]...\nDid you mean to run update-webkit-localizable-strings instead?\n";
-
--f $exceptionsFile or die "Couldn't find exceptions file $exceptionsFile\n" unless !defined $exceptionsFile;
-
-my $fileToUpdate = shift @ARGV;
--f $fileToUpdate or die "Couldn't find file to update $fileToUpdate\n";
-
-my $warnAboutUnlocalizedStrings = defined $exceptionsFile;
-
-my @directories = ();
-if (@ARGV < 1) {
- push(@directories, ".");
-} else {
- for my $dir (@ARGV) {
- push @directories, $dir;
- }
-}
-
-my $sawError = 0;
-
-my $localizedCount = 0;
-my $keyCollisionCount = 0;
-my $notLocalizedCount = 0;
-my $NSLocalizeCount = 0;
-
-my %exception;
-my %usedException;
-
-if (defined $exceptionsFile && open EXCEPTIONS, $exceptionsFile) {
- while (<EXCEPTIONS>) {
- chomp;
- if (/^"([^\\"]|\\.)*"$/ or /^[-_\/\w\s.]+.(h|m|mm|c|cpp)$/ or /^[-_\/\w\s.]+.(h|m|mm|c|cpp):"([^\\"]|\\.)*"$/) {
- if ($exception{$_}) {
- print "$exceptionsFile:$.: warning: exception for $_ appears twice\n";
- print "$exceptionsFile:$exception{$_}: warning: first appearance\n";
- } else {
- $exception{$_} = $.;
- }
- } else {
- print "$exceptionsFile:$.: warning: syntax error\n";
- }
- }
- close EXCEPTIONS;
-}
-
-my $quotedDirectoriesString = '"' . join('" "', @directories) . '"';
-for my $dir (@directoriesToSkip) {
- $quotedDirectoriesString .= ' -path "' . $dir . '" -prune -o';
-}
-
-my @files = ( split "\n", `find $quotedDirectoriesString \\( -name "*.h" -o -name "*.m" -o -name "*.mm" -o -name "*.c" -o -name "*.cpp" \\)` );
-
-for my $file (sort @files) {
- next if $file =~ /\/\w+LocalizableStrings\w*\.h$/ || $file =~ /\/LocalizedStrings\.h$/;
-
- $file =~ s-^./--;
-
- open SOURCE, $file or die "can't open $file\n";
-
- my $inComment = 0;
-
- my $expected = "";
- my $macroLine;
- my $macro;
- my $UIString;
- my $key;
- my $comment;
-
- my $string;
- my $stringLine;
- my $nestingLevel;
-
- my $previousToken = "";
-
- while (<SOURCE>) {
- chomp;
-
- # Handle continued multi-line comment.
- if ($inComment) {
- next unless s-.*\*/--;
- $inComment = 0;
- }
-
- next unless defined $nestingLevel or /(\"|\/\*)/;
-
- # Handle all the tokens in the line.
- while (s-^\s*([#\w]+|/\*|//|[^#\w/'"()\[\],]+|.)--) {
- my $token = $1;
-
- if ($token eq "\"") {
- if ($expected and $expected ne "a quoted string") {
- print "$file:$.: found a quoted string but expected $expected\n";
- $sawError = 1;
- $expected = "";
- }
- if (s-^(([^\\$token]|\\.)*?)$token--) {
- if (!defined $string) {
- $stringLine = $.;
- $string = $1;
- } else {
- $string .= $1;
- }
- } else {
- print "$file:$.: mismatched quotes\n";
- $sawError = 1;
- $_ = "";
- }
- next;
- }
-
- if (defined $string) {
-handleString:
- if ($expected) {
- if (!defined $UIString) {
- # FIXME: Validate UTF-8 here?
- $UIString = $string;
- $expected = ",";
- } elsif (($macro =~ /(WEB_)?UI_STRING_KEY(_INTERNAL)?$/) and !defined $key) {
- # FIXME: Validate UTF-8 here?
- $key = $string;
- $expected = ",";
- } elsif (!defined $comment) {
- # FIXME: Validate UTF-8 here?
- $comment = $string;
- $expected = ")";
- }
- } else {
- if (defined $nestingLevel) {
- # In a debug macro, no need to localize.
- } elsif ($previousToken eq "#include" or $previousToken eq "#import") {
- # File name, no need to localize.
- } elsif ($previousToken eq "extern" and $string eq "C") {
- # extern "C", no need to localize.
- } elsif ($string eq "") {
- # Empty string can sometimes be localized, but we need not complain if not.
- } elsif ($exception{$file}) {
- $usedException{$file} = 1;
- } elsif ($exception{"\"$string\""}) {
- $usedException{"\"$string\""} = 1;
- } elsif ($exception{"$file:\"$string\""}) {
- $usedException{"$file:\"$string\""} = 1;
- } else {
- print "$file:$stringLine: warning: \"$string\" is not marked for localization\n" if $warnAboutUnlocalizedStrings;
- $notLocalizedCount++;
- }
- }
- $string = undef;
- last if !defined $token;
- }
-
- $previousToken = $token;
-
- if ($token =~ /^NSLocalized/ && $token !~ /NSLocalizedDescriptionKey/ && $token !~ /NSLocalizedStringFromTableInBundle/ && $token !~ /NSLocalizedFileSizeDescription/ && $token !~ /NSLocalizedDescriptionKey/ && $token !~ /NSLocalizedRecoverySuggestionErrorKey/) {
- print "$file:$.: found a use of an NSLocalized macro ($token); not supported\n";
- $nestingLevel = 0 if !defined $nestingLevel;
- $sawError = 1;
- $NSLocalizeCount++;
- } elsif ($token eq "/*") {
- if (!s-^.*?\*/--) {
- $_ = ""; # If the comment doesn't end, discard the result of the line and set flag
- $inComment = 1;
- }
- } elsif ($token eq "//") {
- $_ = ""; # Discard the rest of the line
- } elsif ($token eq "'") {
- if (!s-([^\\]|\\.)'--) { #' <-- that single quote makes the Project Builder editor less confused
- print "$file:$.: mismatched single quote\n";
- $sawError = 1;
- $_ = "";
- }
- } else {
- if ($expected and $expected ne $token) {
- print "$file:$.: found $token but expected $expected\n";
- $sawError = 1;
- $expected = "";
- }
- if ($token =~ /(WEB_)?UI_STRING(_KEY)?(_INTERNAL)?$/) {
- $expected = "(";
- $macro = $token;
- $UIString = undef;
- $key = undef;
- $comment = undef;
- $macroLine = $.;
- } elsif ($token eq "(" or $token eq "[") {
- ++$nestingLevel if defined $nestingLevel;
- $expected = "a quoted string" if $expected;
- } elsif ($token eq ",") {
- $expected = "a quoted string" if $expected;
- } elsif ($token eq ")" or $token eq "]") {
- $nestingLevel = undef if defined $nestingLevel && !--$nestingLevel;
- if ($expected) {
- $key = $UIString if !defined $key;
- HandleUIString($UIString, $key, $comment, $file, $macroLine);
- $macro = "";
- $expected = "";
- $localizedCount++;
- }
- } elsif ($isDebugMacro{$token}) {
- $nestingLevel = 0 if !defined $nestingLevel;
- }
- }
- }
-
- }
-
- goto handleString if defined $string;
-
- if ($expected) {
- print "$file: reached end of file but expected $expected\n";
- $sawError = 1;
- }
-
- close SOURCE;
-}
-
-# Unescapes C language hexadecimal escape sequences.
-sub UnescapeHexSequence($)
-{
- my ($originalStr) = @_;
-
- my $escapedStr = $originalStr;
- my $unescapedStr = "";
-
- for (;;) {
- if ($escapedStr =~ s-^\\x([[:xdigit:]]+)--) {
- if (256 <= hex($1)) {
- print "Hexadecimal escape sequence out of range: \\x$1\n";
- return undef;
- }
- $unescapedStr .= pack("H*", $1);
- } elsif ($escapedStr =~ s-^(.)--) {
- $unescapedStr .= $1;
- } else {
- return $unescapedStr;
- }
- }
-}
-
-my %stringByKey;
-my %commentByKey;
-my %fileByKey;
-my %lineByKey;
-
-sub HandleUIString
-{
- my ($string, $key, $comment, $file, $line) = @_;
-
- my $bad = 0;
- $string = UnescapeHexSequence($string);
- if (!defined($string)) {
- print "$file:$line: string has an illegal hexadecimal escape sequence\n";
- $bad = 1;
- }
- $key = UnescapeHexSequence($key);
- if (!defined($key)) {
- print "$file:$line: key has an illegal hexadecimal escape sequence\n";
- $bad = 1;
- }
- $comment = UnescapeHexSequence($comment);
- if (!defined($comment)) {
- print "$file:$line: comment has an illegal hexadecimal escape sequence\n";
- $bad = 1;
- }
- if (grep { $_ == 0xFFFD } unpack "U*", $string) {
- print "$file:$line: string for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n";
- $bad = 1;
- }
- if ($string ne $key && grep { $_ == 0xFFFD } unpack "U*", $key) {
- print "$file:$line: key has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n";
- $bad = 1;
- }
- if (grep { $_ == 0xFFFD } unpack "U*", $comment) {
- print "$file:$line: comment for translation has illegal UTF-8 -- most likely a problem with the Text Encoding of the source file\n";
- $bad = 1;
- }
- if ($bad) {
- $sawError = 1;
- return;
- }
-
- if ($stringByKey{$key} && $stringByKey{$key} ne $string) {
- print "$file:$line: warning: encountered the same key, \"$key\", twice, with different strings\n";
- print "$fileByKey{$key}:$lineByKey{$key}: warning: previous occurrence\n";
- $keyCollisionCount++;
- return;
- }
- if ($commentByKey{$key} && $commentByKey{$key} ne $comment) {
- print "$file:$line: warning: encountered the same key, \"$key\", twice, with different comments\n";
- print "$fileByKey{$key}:$lineByKey{$key}: warning: previous occurrence\n";
- $keyCollisionCount++;
- return;
- }
-
- $fileByKey{$key} = $file;
- $lineByKey{$key} = $line;
- $stringByKey{$key} = $string;
- $commentByKey{$key} = $comment;
-}
-
-print "\n" if $sawError || $notLocalizedCount || $NSLocalizeCount;
-
-my @unusedExceptions = sort grep { !$usedException{$_} } keys %exception;
-if (@unusedExceptions) {
- for my $unused (@unusedExceptions) {
- print "$exceptionsFile:$exception{$unused}: warning: exception $unused not used\n";
- }
- print "\n";
-}
-
-print "$localizedCount localizable strings\n" if $localizedCount;
-print "$keyCollisionCount key collisions\n" if $keyCollisionCount;
-print "$notLocalizedCount strings not marked for localization\n" if $notLocalizedCount;
-print "$NSLocalizeCount uses of NSLocalize\n" if $NSLocalizeCount;
-print scalar(@unusedExceptions), " unused exceptions\n" if @unusedExceptions;
-
-if ($sawError) {
- print "\nErrors encountered. Exiting without writing to $fileToUpdate.\n";
- exit 1;
-}
-
-my $localizedStrings = "";
-
-for my $key (sort keys %commentByKey) {
- $localizedStrings .= "/* $commentByKey{$key} */\n\"$key\" = \"$stringByKey{$key}\";\n\n";
-}
-
-if (-e "$fileToUpdate") {
- if (!$verify) {
- # Write out the strings file as UTF-8
- open STRINGS, ">", "$fileToUpdate" or die;
- print STRINGS $localizedStrings;
- close STRINGS;
- } else {
- open STRINGS, $fileToUpdate or die;
-
- my $lastComment;
- my $line;
-
- while (<STRINGS>) {
- chomp;
-
- next if (/^\s*$/);
-
- if (/^\/\* (.*) \*\/$/) {
- $lastComment = $1;
- } elsif (/^"((?:[^\\]|\\[^"])*)"\s*=\s*"((?:[^\\]|\\[^"])*)";$/) #
- {
- my $string = delete $stringByKey{$1};
- if (!defined $string) {
- print "$fileToUpdate:$.: unused key \"$1\"\n";
- $sawError = 1;
- } else {
- if (!($string eq $2)) {
- print "$fileToUpdate:$.: unexpected value \"$2\" for key \"$1\"\n";
- print "$fileByKey{$1}:$lineByKey{$1}: expected value \"$string\" defined here\n";
- $sawError = 1;
- }
- if (!($lastComment eq $commentByKey{$1})) {
- print "$fileToUpdate:$.: unexpected comment /* $lastComment */ for key \"$1\"\n";
- print "$fileByKey{$1}:$lineByKey{$1}: expected comment /* $commentByKey{$1} */ defined here\n";
- $sawError = 1;
- }
- }
- } else {
- print "$fileToUpdate:$.: line with unexpected format: $_\n";
- $sawError = 1;
- }
- }
-
- for my $missing (keys %stringByKey) {
- print "$fileByKey{$missing}:$lineByKey{$missing}: missing key \"$missing\"\n";
- $sawError = 1;
- }
-
- if ($sawError) {
- print "\n$fileToUpdate:0: file is not up to date.\n";
- exit 1;
- }
- }
-} else {
- print "error: $fileToUpdate does not exist\n";
- exit 1;
-}
+exec "$(dirname $0)/../../Source/WebCore/extract-localizable-strings.pl" "$@"
Modified: trunk/Tools/Scripts/update-webkit-localizable-strings (156190 => 156191)
--- trunk/Tools/Scripts/update-webkit-localizable-strings 2013-09-20 19:56:33 UTC (rev 156190)
+++ trunk/Tools/Scripts/update-webkit-localizable-strings 2013-09-20 20:13:11 UTC (rev 156191)
@@ -45,5 +45,5 @@
chdirWebKit();
-system "Tools/Scripts/extract-localizable-strings", $webCoreFileToUpdate, @webKitDirectoriesToScan;
+system "Source/WebCore/extract-localizable-strings.pl", $webCoreFileToUpdate, @webKitDirectoriesToScan;
system "Tools/Scripts/extract-localizable-js-strings", $webInspectorUIFileToUpdate, @webInspectorUIDirectoriesToScan;