Commit effa54c4 authored by toyoshim@chromium.org's avatar toyoshim@chromium.org

Translate: adopt html lang attribute if valid value is provided

Language decision is made by heuristics using Content-Language and CLD
determined language. This change adds html lang attribute, e.g.,
<html lang="ja">, as a third hint for language decision.
Content-Language is often invalid due to invalid server configuration.
On the other hand, lang attribute is provided by pages, or authoring
tools or authors themselves. As a result, they are more reliable than
Content-Language. With this change, language decision uses html lang
attribute instead of Content-Language if valid value is provided.
Other dicision process is not changed at all.

BUG=222073
TEST=unit_tests, browser_tests

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=201856

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=202427

Review URL: https://chromiumcodereview.appspot.com/15728002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202531 0039d316-1c4b-4281-b951-d872f2087c98
parent 7d7a50d4
...@@ -93,18 +93,28 @@ void TranslateHelper::PageCaptured(const string16& contents) { ...@@ -93,18 +93,28 @@ void TranslateHelper::PageCaptured(const string16& contents) {
// language of the intended audience (a distinction really only // language of the intended audience (a distinction really only
// relevant for things like langauge textbooks). This distinction // relevant for things like langauge textbooks). This distinction
// shouldn't affect translation. // shouldn't affect translation.
WebDocument document = GetMainFrame()->document(); WebFrame* main_frame = GetMainFrame();
if (!main_frame)
return;
WebDocument document = main_frame->document();
std::string content_language = document.contentLanguage().utf8(); std::string content_language = document.contentLanguage().utf8();
WebElement html_element = document.documentElement();
std::string html_lang;
// |html_element| can be null element, e.g. in
// BrowserTest.WindowOpenClose.
if (!html_element.isNull())
html_lang = html_element.getAttribute("lang").utf8();
std::string cld_language; std::string cld_language;
bool is_cld_reliable; bool is_cld_reliable;
std::string language = DeterminePageLanguage( std::string language = DeterminePageLanguage(
content_language, contents, &cld_language, &is_cld_reliable); content_language, html_lang, contents, &cld_language, &is_cld_reliable);
if (language.empty()) if (language.empty())
return; return;
language_determined_time_ = base::TimeTicks::Now(); language_determined_time_ = base::TimeTicks::Now();
// TODO(toyoshim): Add |html_lang| to LanguageDetectionDetails.
GURL url(document.url()); GURL url(document.url());
LanguageDetectionDetails details; LanguageDetectionDetails details;
details.time = base::Time::Now(); details.time = base::Time::Now();
...@@ -318,8 +328,21 @@ void TranslateHelper::ResetInvalidLanguageCode(std::string* code) { ...@@ -318,8 +328,21 @@ void TranslateHelper::ResetInvalidLanguageCode(std::string* code) {
} }
} }
// static
void TranslateHelper::ApplyLanguageCodeCorrection(std::string* code) {
// Correct well-known format errors.
CorrectLanguageCodeTypo(code);
// Convert language code synonym firstly because sometime synonym code is in
// invalid format, e.g. 'fil'. After validation, such a 3 characters language
// gets converted to an empty string.
ConvertLanguageCodeSynonym(code);
ResetInvalidLanguageCode(code);
}
// static // static
std::string TranslateHelper::DeterminePageLanguage(const std::string& code, std::string TranslateHelper::DeterminePageLanguage(const std::string& code,
const std::string& html_lang,
const string16& contents, const string16& contents,
std::string* cld_language_p, std::string* cld_language_p,
bool* is_cld_reliable_p) { bool* is_cld_reliable_p) {
...@@ -337,17 +360,27 @@ std::string TranslateHelper::DeterminePageLanguage(const std::string& code, ...@@ -337,17 +360,27 @@ std::string TranslateHelper::DeterminePageLanguage(const std::string& code,
ConvertLanguageCodeSynonym(&cld_language); ConvertLanguageCodeSynonym(&cld_language);
#endif // defined(ENABLE_LANGUAGE_DETECTION) #endif // defined(ENABLE_LANGUAGE_DETECTION)
// Correct well-known format errors. // Check if html lang attribute is valid.
std::string language = code; std::string modified_html_lang;
CorrectLanguageCodeTypo(&language); if (!html_lang.empty()) {
modified_html_lang = html_lang;
ApplyLanguageCodeCorrection(&modified_html_lang);
TranslateHelperMetrics::ReportHtmlLang(html_lang, modified_html_lang);
VLOG(9) << "html lang based language code: " << modified_html_lang;
}
// Convert language code synonym firstly because sometime synonym code is in // Check if Content-Language is valid.
// invalid format, e.g. 'fil'. After validation, such a 3 characters language std::string modified_code;
// gets converted to an empty string. if (!code.empty()) {
ConvertLanguageCodeSynonym(&language); modified_code = code;
ResetInvalidLanguageCode(&language); ApplyLanguageCodeCorrection(&modified_code);
TranslateHelperMetrics::ReportContentLanguage(code, modified_code);
}
TranslateHelperMetrics::ReportContentLanguage(code, language); // Adopt |modified_html_lang| if it is valid. Otherwise, adopt
// |modified_code|.
std::string language = modified_html_lang.empty() ? modified_code :
modified_html_lang;
#if defined(ENABLE_LANGUAGE_DETECTION) #if defined(ENABLE_LANGUAGE_DETECTION)
// If |language| is empty, just use CLD result even though it might be // If |language| is empty, just use CLD result even though it might be
...@@ -433,7 +466,8 @@ void TranslateHelper::OnTranslatePage(int page_id, ...@@ -433,7 +466,8 @@ void TranslateHelper::OnTranslatePage(int page_id,
const std::string& translate_script, const std::string& translate_script,
const std::string& source_lang, const std::string& source_lang,
const std::string& target_lang) { const std::string& target_lang) {
if (render_view()->GetPageId() != page_id) WebFrame* main_frame = GetMainFrame();
if (!main_frame || render_view()->GetPageId() != page_id)
return; // We navigated away, nothing to do. return; // We navigated away, nothing to do.
if (translation_pending_ && page_id == page_id_ && if (translation_pending_ && page_id == page_id_ &&
...@@ -457,7 +491,7 @@ void TranslateHelper::OnTranslatePage(int page_id, ...@@ -457,7 +491,7 @@ void TranslateHelper::OnTranslatePage(int page_id,
TranslateHelperMetrics::ReportUserActionDuration(language_determined_time_, TranslateHelperMetrics::ReportUserActionDuration(language_determined_time_,
base::TimeTicks::Now()); base::TimeTicks::Now());
GURL url(GetMainFrame()->document().url()); GURL url(main_frame->document().url());
TranslateHelperMetrics::ReportPageScheme(url.scheme()); TranslateHelperMetrics::ReportPageScheme(url.scheme());
if (!IsTranslateLibAvailable()) { if (!IsTranslateLibAvailable()) {
...@@ -590,12 +624,10 @@ void TranslateHelper::NotifyBrowserTranslationFailed( ...@@ -590,12 +624,10 @@ void TranslateHelper::NotifyBrowserTranslationFailed(
WebFrame* TranslateHelper::GetMainFrame() { WebFrame* TranslateHelper::GetMainFrame() {
WebView* web_view = render_view()->GetWebView(); WebView* web_view = render_view()->GetWebView();
if (!web_view) {
// When the WebView is going away, the render view should have called // When the tab is going to be closed, the web_view can be NULL.
// CancelPendingTranslation() which should have stopped any pending work, so if (!web_view)
// that case should not happen.
NOTREACHED();
return NULL; return NULL;
}
return web_view->mainFrame(); return web_view->mainFrame();
} }
...@@ -96,18 +96,23 @@ class TranslateHelper : public content::RenderViewObserver { ...@@ -96,18 +96,23 @@ class TranslateHelper : public content::RenderViewObserver {
CLDAgreeWithLanguageCodeHavingCountryCode); CLDAgreeWithLanguageCodeHavingCountryCode);
FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest,
InvalidLanguageMetaTagProviding); InvalidLanguageMetaTagProviding);
FRIEND_TEST_ALL_PREFIXES(TranslateHelperTest, AdoptHtmlLang);
// Correct language code if it contains well-known mistakes. // Corrects language code if it contains well-known mistakes.
static void CorrectLanguageCodeTypo(std::string* code); static void CorrectLanguageCodeTypo(std::string* code);
// Convert language code to the one used in server supporting list. // Converts language code to the one used in server supporting list.
static void ConvertLanguageCodeSynonym(std::string* code); static void ConvertLanguageCodeSynonym(std::string* code);
// Reset language code if the specified string is apparently invalid. // Resets language code if the specified string is apparently invalid.
static void ResetInvalidLanguageCode(std::string* code); static void ResetInvalidLanguageCode(std::string* code);
// Determine content page language from Content-Language code and contents. // Applies a series of language code modification in proper order.
static void ApplyLanguageCodeCorrection(std::string* code);
// Determines content page language from Content-Language code and contents.
static std::string DeterminePageLanguage(const std::string& code, static std::string DeterminePageLanguage(const std::string& code,
const std::string& html_lang,
const string16& contents, const string16& contents,
std::string* cld_language, std::string* cld_language,
bool* is_cld_reliable); bool* is_cld_reliable);
......
...@@ -13,6 +13,7 @@ namespace { ...@@ -13,6 +13,7 @@ namespace {
// a corresponding index in MetricsNameIndex and an entry in |kMetricsEntries|. // a corresponding index in MetricsNameIndex and an entry in |kMetricsEntries|.
const char kRenderer4LanguageDetection[] = "Renderer4.LanguageDetection"; const char kRenderer4LanguageDetection[] = "Renderer4.LanguageDetection";
const char kTranslateContentLanguage[] = "Translate.ContentLanguage"; const char kTranslateContentLanguage[] = "Translate.ContentLanguage";
const char kTranslateHtmlLang[] = "Translate.HtmlLang";
const char kTranslateLanguageVerification[] = "Translate.LanguageVerification"; const char kTranslateLanguageVerification[] = "Translate.LanguageVerification";
const char kTranslateTimeToBeReady[] = "Translate.TimeToBeReady"; const char kTranslateTimeToBeReady[] = "Translate.TimeToBeReady";
const char kTranslateTimeToLoad[] = "Translate.TimeToLoad"; const char kTranslateTimeToLoad[] = "Translate.TimeToLoad";
...@@ -34,6 +35,8 @@ const MetricsEntry kMetricsEntries[] = { ...@@ -34,6 +35,8 @@ const MetricsEntry kMetricsEntries[] = {
kRenderer4LanguageDetection }, kRenderer4LanguageDetection },
{ TranslateHelperMetrics::UMA_CONTENT_LANGUAGE, { TranslateHelperMetrics::UMA_CONTENT_LANGUAGE,
kTranslateContentLanguage }, kTranslateContentLanguage },
{ TranslateHelperMetrics::UMA_HTML_LANG,
kTranslateHtmlLang },
{ TranslateHelperMetrics::UMA_LANGUAGE_VERIFICATION, { TranslateHelperMetrics::UMA_LANGUAGE_VERIFICATION,
kTranslateLanguageVerification }, kTranslateLanguageVerification },
{ TranslateHelperMetrics::UMA_TIME_TO_BE_READY, { TranslateHelperMetrics::UMA_TIME_TO_BE_READY,
...@@ -51,25 +54,32 @@ const MetricsEntry kMetricsEntries[] = { ...@@ -51,25 +54,32 @@ const MetricsEntry kMetricsEntries[] = {
COMPILE_ASSERT(arraysize(kMetricsEntries) == TranslateHelperMetrics::UMA_MAX, COMPILE_ASSERT(arraysize(kMetricsEntries) == TranslateHelperMetrics::UMA_MAX,
arraysize_of_kMetricsEntries_should_be_UMA_MAX); arraysize_of_kMetricsEntries_should_be_UMA_MAX);
TranslateHelperMetrics::LanguageCheckType GetLanguageCheckMetric(
const std::string& provided_code,
const std::string& revised_code) {
if (provided_code.empty())
return TranslateHelperMetrics::LANGUAGE_NOT_PROVIDED;
else if (provided_code == revised_code)
return TranslateHelperMetrics::LANGUAGE_VALID;
return TranslateHelperMetrics::LANGUAGE_INVALID;
}
} // namespace } // namespace
namespace TranslateHelperMetrics { namespace TranslateHelperMetrics {
void ReportContentLanguage(const std::string& provided_code, void ReportContentLanguage(const std::string& provided_code,
const std::string& revised_code) { const std::string& revised_code) {
if (provided_code.empty()) { UMA_HISTOGRAM_ENUMERATION(kTranslateContentLanguage,
UMA_HISTOGRAM_ENUMERATION(kTranslateContentLanguage, GetLanguageCheckMetric(provided_code, revised_code),
CONTENT_LANGUAGE_NOT_PROVIDED, TranslateHelperMetrics::LANGUAGE_MAX);
CONTENT_LANGUAGE_MAX); }
} else if (provided_code == revised_code) {
UMA_HISTOGRAM_ENUMERATION(kTranslateContentLanguage, void ReportHtmlLang(const std::string& provided_code,
CONTENT_LANGUAGE_VALID, const std::string& revised_code) {
CONTENT_LANGUAGE_MAX); UMA_HISTOGRAM_ENUMERATION(kTranslateHtmlLang,
} else { GetLanguageCheckMetric(provided_code, revised_code),
UMA_HISTOGRAM_ENUMERATION(kTranslateContentLanguage, TranslateHelperMetrics::LANGUAGE_MAX);
CONTENT_LANGUAGE_INVALID,
CONTENT_LANGUAGE_MAX);
}
} }
void ReportLanguageVerification(LanguageVerificationType type) { void ReportLanguageVerification(LanguageVerificationType type) {
......
...@@ -16,6 +16,7 @@ namespace TranslateHelperMetrics { ...@@ -16,6 +16,7 @@ namespace TranslateHelperMetrics {
enum MetricsNameIndex { enum MetricsNameIndex {
UMA_LANGUAGE_DETECTION, UMA_LANGUAGE_DETECTION,
UMA_CONTENT_LANGUAGE, UMA_CONTENT_LANGUAGE,
UMA_HTML_LANG,
UMA_LANGUAGE_VERIFICATION, UMA_LANGUAGE_VERIFICATION,
UMA_TIME_TO_BE_READY, UMA_TIME_TO_BE_READY,
UMA_TIME_TO_LOAD, UMA_TIME_TO_LOAD,
...@@ -27,11 +28,11 @@ enum MetricsNameIndex { ...@@ -27,11 +28,11 @@ enum MetricsNameIndex {
// A page may provide a Content-Language HTTP header or a META tag. // A page may provide a Content-Language HTTP header or a META tag.
// TranslateHelper checks if a server provides a valid Content-Language. // TranslateHelper checks if a server provides a valid Content-Language.
enum ContentLanguageType { enum LanguageCheckType {
CONTENT_LANGUAGE_NOT_PROVIDED, LANGUAGE_NOT_PROVIDED,
CONTENT_LANGUAGE_VALID, LANGUAGE_VALID,
CONTENT_LANGUAGE_INVALID, LANGUAGE_INVALID,
CONTENT_LANGUAGE_MAX, LANGUAGE_MAX,
}; };
// When a valid Content-Language is provided, TranslateHelper checks if a // When a valid Content-Language is provided, TranslateHelper checks if a
...@@ -54,12 +55,19 @@ enum SchemeType { ...@@ -54,12 +55,19 @@ enum SchemeType {
}; };
// Called after TranslateHelper verifies a server providing Content-Language // Called after TranslateHelper verifies a server providing Content-Language
// header. |provided_code| contains a Content-Language header value which // header. |provided_code| contains a Content-Language header value which a
// server provides. It can be empty string when a server doesn't provide it. // server provides. It can be empty string when a server doesn't provide it.
// |revised_code| is a value modified by format error corrector. // |revised_code| is a value modified by format error corrector.
void ReportContentLanguage(const std::string& provided_code, void ReportContentLanguage(const std::string& provided_code,
const std::string& revised_code); const std::string& revised_code);
// Called after TranslateHelper verifies a page providing html lang attribute.
// |provided_code| contains a html lang attribute which a page provides. It can
// be empty string when a page doesn't provide it. |revised_code| is a value
// modified by format error corrector.
void ReportHtmlLang(const std::string& provided_code,
const std::string& revised_code);
// Called when CLD verifies Content-Language header. // Called when CLD verifies Content-Language header.
void ReportLanguageVerification(LanguageVerificationType type); void ReportLanguageVerification(LanguageVerificationType type);
......
...@@ -33,23 +33,20 @@ class MetricsRecorder { ...@@ -33,23 +33,20 @@ class MetricsRecorder {
base_samples_ = histogram->SnapshotSamples(); base_samples_ = histogram->SnapshotSamples();
} }
void CheckContentLanguage(int expected_not_provided, void CheckLanguage(TranslateHelperMetrics::MetricsNameIndex index,
int expected_valid, int expected_not_provided,
int expected_invalid) { int expected_valid,
ASSERT_EQ(TranslateHelperMetrics::GetMetricsName( int expected_invalid) {
TranslateHelperMetrics::UMA_CONTENT_LANGUAGE), key_); ASSERT_EQ(TranslateHelperMetrics::GetMetricsName(index), key_);
Snapshot(); Snapshot();
EXPECT_EQ( EXPECT_EQ(expected_not_provided,
expected_not_provided, GetCount(TranslateHelperMetrics::LANGUAGE_NOT_PROVIDED));
GetCount(TranslateHelperMetrics::CONTENT_LANGUAGE_NOT_PROVIDED)); EXPECT_EQ(expected_valid,
EXPECT_EQ( GetCount(TranslateHelperMetrics::LANGUAGE_VALID));
expected_valid, EXPECT_EQ(expected_invalid,
GetCount(TranslateHelperMetrics::CONTENT_LANGUAGE_VALID)); GetCount(TranslateHelperMetrics::LANGUAGE_INVALID));
EXPECT_EQ(
expected_invalid,
GetCount(TranslateHelperMetrics::CONTENT_LANGUAGE_INVALID));
} }
void CheckLanguageVerification(int expected_cld_disabled, void CheckLanguageVerification(int expected_cld_disabled,
...@@ -150,13 +147,26 @@ TEST(TranslateHelperMetricsTest, ReportContentLanguage) { ...@@ -150,13 +147,26 @@ TEST(TranslateHelperMetricsTest, ReportContentLanguage) {
MetricsRecorder recorder(TranslateHelperMetrics::GetMetricsName( MetricsRecorder recorder(TranslateHelperMetrics::GetMetricsName(
TranslateHelperMetrics::UMA_CONTENT_LANGUAGE)); TranslateHelperMetrics::UMA_CONTENT_LANGUAGE));
recorder.CheckContentLanguage(0, 0, 0); recorder.CheckLanguage(TranslateHelperMetrics::UMA_CONTENT_LANGUAGE, 0, 0, 0);
TranslateHelperMetrics::ReportContentLanguage(std::string(), std::string()); TranslateHelperMetrics::ReportContentLanguage(std::string(), std::string());
recorder.CheckContentLanguage(1, 0, 0); recorder.CheckLanguage(TranslateHelperMetrics::UMA_CONTENT_LANGUAGE, 1, 0, 0);
TranslateHelperMetrics::ReportContentLanguage("ja_JP", "ja-JP"); TranslateHelperMetrics::ReportContentLanguage("ja_JP", "ja-JP");
recorder.CheckContentLanguage(1, 0, 1); recorder.CheckLanguage(TranslateHelperMetrics::UMA_CONTENT_LANGUAGE, 1, 0, 1);
TranslateHelperMetrics::ReportContentLanguage("en", "en"); TranslateHelperMetrics::ReportContentLanguage("en", "en");
recorder.CheckContentLanguage(1, 1, 1); recorder.CheckLanguage(TranslateHelperMetrics::UMA_CONTENT_LANGUAGE, 1, 1, 1);
}
TEST(TranslateHelperMetricsTest, ReportHtmlLang) {
MetricsRecorder recorder(TranslateHelperMetrics::GetMetricsName(
TranslateHelperMetrics::UMA_HTML_LANG));
recorder.CheckLanguage(TranslateHelperMetrics::UMA_HTML_LANG, 0, 0, 0);
TranslateHelperMetrics::ReportHtmlLang(std::string(), std::string());
recorder.CheckLanguage(TranslateHelperMetrics::UMA_HTML_LANG, 1, 0, 0);
TranslateHelperMetrics::ReportHtmlLang("ja_JP", "ja-JP");
recorder.CheckLanguage(TranslateHelperMetrics::UMA_HTML_LANG, 1, 0, 1);
TranslateHelperMetrics::ReportHtmlLang("en", "en");
recorder.CheckLanguage(TranslateHelperMetrics::UMA_HTML_LANG, 1, 1, 1);
} }
TEST(TranslateHelperMetricsTest, ReportLanguageVerification) { TEST(TranslateHelperMetricsTest, ReportLanguageVerification) {
......
...@@ -90,8 +90,9 @@ TEST_F(TranslateHelperTest, CLDDisagreeWithWrongLanguageCode) { ...@@ -90,8 +90,9 @@ TEST_F(TranslateHelperTest, CLDDisagreeWithWrongLanguageCode) {
std::string cld_language; std::string cld_language;
bool is_cld_reliable; bool is_cld_reliable;
std::string language = std::string language =
TranslateHelper::DeterminePageLanguage(std::string("ja"), contents, TranslateHelper::DeterminePageLanguage(std::string("ja"), std::string(),
&cld_language, &is_cld_reliable); contents, &cld_language,
&is_cld_reliable);
EXPECT_EQ(chrome::kUnknownLanguageCode, language); EXPECT_EQ(chrome::kUnknownLanguageCode, language);
EXPECT_EQ("en", cld_language); EXPECT_EQ("en", cld_language);
EXPECT_TRUE(is_cld_reliable); EXPECT_TRUE(is_cld_reliable);
...@@ -108,7 +109,8 @@ TEST_F(TranslateHelperTest, CLDAgreeWithLanguageCodeHavingCountryCode) { ...@@ -108,7 +109,8 @@ TEST_F(TranslateHelperTest, CLDAgreeWithLanguageCodeHavingCountryCode) {
std::string cld_language; std::string cld_language;
bool is_cld_reliable; bool is_cld_reliable;
std::string language = std::string language =
TranslateHelper::DeterminePageLanguage(std::string("en-US"), contents, TranslateHelper::DeterminePageLanguage(std::string("en-US"),
std::string(), contents,
&cld_language, &is_cld_reliable); &cld_language, &is_cld_reliable);
EXPECT_EQ("en-US", language); EXPECT_EQ("en-US", language);
EXPECT_EQ("en", cld_language); EXPECT_EQ("en", cld_language);
...@@ -126,9 +128,30 @@ TEST_F(TranslateHelperTest, InvalidLanguageMetaTagProviding) { ...@@ -126,9 +128,30 @@ TEST_F(TranslateHelperTest, InvalidLanguageMetaTagProviding) {
std::string cld_language; std::string cld_language;
bool is_cld_reliable; bool is_cld_reliable;
std::string language = std::string language =
TranslateHelper::DeterminePageLanguage(std::string("utf-8"), contents, TranslateHelper::DeterminePageLanguage(std::string("utf-8"),
std::string(), contents,
&cld_language, &is_cld_reliable); &cld_language, &is_cld_reliable);
EXPECT_EQ("en", language); EXPECT_EQ("en", language);
EXPECT_EQ("en", cld_language); EXPECT_EQ("en", cld_language);
EXPECT_TRUE(is_cld_reliable); EXPECT_TRUE(is_cld_reliable);
} }
// Tests that the language meta tag providing wrong information is ignored
// because of valid html lang attribute.
TEST_F(TranslateHelperTest, AdoptHtmlLang) {
string16 contents = ASCIIToUTF16(
"<html lang='en'><head><meta http-equiv='Content-Language' content='ja'>"
"</head><body>This is a page apparently written in English. Even though "
"content-language is provided, the value will be ignored if the value "
"is suspicious.</body></html>");
std::string cld_language;
bool is_cld_reliable;
std::string language =
TranslateHelper::DeterminePageLanguage(std::string("ja"),
std::string("en"),
contents, &cld_language,
&is_cld_reliable);
EXPECT_EQ("en", language);
EXPECT_EQ("en", cld_language);
EXPECT_TRUE(is_cld_reliable);
}
...@@ -8950,13 +8950,20 @@ other types of suffix sets. ...@@ -8950,13 +8950,20 @@ other types of suffix sets.
</summary> </summary>
</histogram> </histogram>
<histogram name="Translate.ContentLanguage" enum="TranslateContentLanguage"> <histogram name="Translate.ContentLanguage" enum="TranslateLanguage">
<summary> <summary>
A page may provide a Content-Language HTTP header or a META tag. For each A page may provide a Content-Language HTTP header or a META tag. For each
page load, measures whether the Content-Language header exists and is valid. page load, measures whether the Content-Language header exists and is valid.
</summary> </summary>
</histogram> </histogram>
<histogram name="Translate.HtmlLang" enum="TranslateLanguage">
<summary>
A page may provide a lang attribute in html tag. For each page load,
measures whether the lang attribute exists and is valid.
</summary>
</histogram>
<histogram name="Translate.InitiationStatus" enum="TranslateInitiationStatus"> <histogram name="Translate.InitiationStatus" enum="TranslateInitiationStatus">
<summary> <summary>
The reason why Chrome decided to perform the next action (e.g., to show The reason why Chrome decided to perform the next action (e.g., to show
...@@ -14073,12 +14080,6 @@ other types of suffix sets. ...@@ -14073,12 +14080,6 @@ other types of suffix sets.
</int> </int>
</enum> </enum>
<enum name="TranslateContentLanguage" type="int">
<int value="0" label="No Content-Language"/>
<int value="1" label="Valid Content-Language"/>
<int value="2" label="Invalid Content-Language"/>
</enum>
<enum name="TranslateError" type="int"> <enum name="TranslateError" type="int">
<int value="0" label="No error"/> <int value="0" label="No error"/>
<int value="1" label="Network error"/> <int value="1" label="Network error"/>
...@@ -14102,6 +14103,12 @@ other types of suffix sets. ...@@ -14102,6 +14103,12 @@ other types of suffix sets.
<int value="9" label="Show infobar"/> <int value="9" label="Show infobar"/>
</enum> </enum>
<enum name="TranslateLanguage" type="int">
<int value="0" label="No language code"/>
<int value="1" label="Valid language code"/>
<int value="2" label="Invalid language code"/>
</enum>
<enum name="TranslateLanguageVerification" type="int"> <enum name="TranslateLanguageVerification" type="int">
<int value="0" label="CLD is disabled"/> <int value="0" label="CLD is disabled"/>
<int value="1" label="No Content-Language"/> <int value="1" label="No Content-Language"/>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment