| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * @fileoverview 'settings-translate-page' is the settings page |
| * translate settings. |
| */ |
| |
| import 'chrome://resources/cr_elements/cr_button/cr_button.js'; |
| import 'chrome://resources/cr_elements/cr_collapse/cr_collapse.js'; |
| import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; |
| import 'chrome://resources/cr_elements/icons.html.js'; |
| import 'chrome://resources/cr_elements/cr_shared_style.css.js'; |
| import 'chrome://resources/cr_elements/md_select.css.js'; |
| import './add_languages_dialog.js'; |
| import './languages.js'; |
| import '../controls/settings_toggle_button.js'; |
| import '../icons.html.js'; |
| import '../settings_shared.css.js'; |
| |
| import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; |
| import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; |
| import {assert} from 'chrome://resources/js/assert.js'; |
| import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js'; |
| import type {DomRepeatEvent} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; |
| |
| import type {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; |
| |
| import {getLanguageHelperInstance} from './languages.js'; |
| import type {LanguageSettingsMetricsProxy} from './languages_settings_metrics_proxy.js'; |
| import {LanguageSettingsActionType, LanguageSettingsMetricsProxyImpl} from './languages_settings_metrics_proxy.js'; |
| import type {LanguageHelper, LanguagesModel} from './languages_types.js'; |
| import {convertLanguageCodeForChrome, getFullName, isTranslateBaseLanguage} from './languages_util.js'; |
| import {getTemplate} from './translate_page.html.js'; |
| |
| const SettingsTranslatePageElementBase = PrefsMixin(I18nMixin(PolymerElement)); |
| |
| export class SettingsTranslatePageElement extends |
| SettingsTranslatePageElementBase { |
| static get is() { |
| return 'settings-translate-page'; |
| } |
| |
| static get template() { |
| return getTemplate(); |
| } |
| |
| static get properties() { |
| return { |
| /** |
| * Read-only reference to the languages model provided by the |
| * 'settings-languages' instance. |
| */ |
| languages: Object, |
| |
| showAddAlwaysTranslateDialog_: Boolean, |
| showAddNeverTranslateDialog_: Boolean, |
| addLanguagesDialogLanguages_: Array, |
| }; |
| } |
| |
| declare languages?: LanguagesModel; |
| declare private showAddAlwaysTranslateDialog_: boolean; |
| declare private showAddNeverTranslateDialog_: boolean; |
| declare private addLanguagesDialogLanguages_: |
| chrome.languageSettingsPrivate.Language[]|null; |
| private languageHelper_: LanguageHelper; |
| private languageSettingsMetricsProxy_: LanguageSettingsMetricsProxy = |
| LanguageSettingsMetricsProxyImpl.getInstance(); |
| |
| override connectedCallback() { |
| super.connectedCallback(); |
| |
| this.languageHelper_ = getLanguageHelperInstance(); |
| } |
| |
| private onTargetLanguageChange_() { |
| this.languageHelper_.setTranslateTargetLanguage( |
| this.shadowRoot!.querySelector<HTMLSelectElement>( |
| '#targetLanguage')!.value); |
| this.languageSettingsMetricsProxy_.recordSettingsMetric( |
| LanguageSettingsActionType.CHANGE_TRANSLATE_TARGET); |
| } |
| |
| /** |
| * Helper function to get the text to display in the target language drop down |
| * list. Returns the display name in the current UI language and the native |
| * name of the language. |
| */ |
| private getTargetLanguageDisplayOption_( |
| item: chrome.languageSettingsPrivate.Language): string { |
| return getFullName(item); |
| } |
| |
| /** |
| * Checks if a Chrome language code is equal to the translate language code. |
| * Used in the translate language selector. If the item matches the translate |
| * target language, it will set that item as selected. |
| */ |
| private translateLanguageEqual_( |
| chromeItemCode: string, translateTarget: string): boolean { |
| return chromeItemCode === convertLanguageCodeForChrome(translateTarget); |
| } |
| |
| /** |
| * A function used for sorting languages alphabetically by display name. |
| */ |
| private alphabeticalSort_( |
| first: chrome.languageSettingsPrivate.Language, |
| second: chrome.languageSettingsPrivate.Language) { |
| return first.displayName.localeCompare(second.displayName); |
| } |
| |
| /** |
| * A filter function to return true if language is not undefined and has a |
| * displayName. |
| */ |
| private hasDisplayName_(language: chrome.languageSettingsPrivate.Language| |
| undefined): boolean { |
| return !!language && !!language.displayName; |
| } |
| |
| /** |
| * Stamps and opens the Add Languages dialog, registering a listener to |
| * disable the dialog's dom-if again on close. |
| */ |
| private onAddAlwaysTranslateLanguagesClick_(e: Event) { |
| e.preventDefault(); |
| const translatableLanguages = this.getTranslatableLanguages_(); |
| this.addLanguagesDialogLanguages_ = translatableLanguages.filter( |
| language => !this.languages!.alwaysTranslate.includes(language)); |
| this.showAddAlwaysTranslateDialog_ = true; |
| } |
| |
| private onAlwaysTranslateDialogClose_() { |
| this.showAddAlwaysTranslateDialog_ = false; |
| this.addLanguagesDialogLanguages_ = null; |
| const toFocus = |
| this.shadowRoot!.querySelector<HTMLElement>('#addAlwaysTranslate'); |
| assert(toFocus); |
| focusWithoutInk(toFocus); |
| } |
| |
| /** |
| * Helper function fired by the add dialog's on-languages-added event. Adds |
| * selected languages to the always-translate languages list. |
| */ |
| private onAlwaysTranslateLanguagesAdded_(e: CustomEvent<string[]>) { |
| const languagesToAdd = e.detail; |
| languagesToAdd.forEach(languageCode => { |
| this.languageHelper_.setLanguageAlwaysTranslateState(languageCode, true); |
| this.languageSettingsMetricsProxy_.recordSettingsMetric( |
| LanguageSettingsActionType.ADD_TO_ALWAYS_TRANSLATE); |
| }); |
| } |
| |
| /** |
| * Removes a language from the always translate languages list. |
| */ |
| private onRemoveAlwaysTranslateLanguageClick_( |
| e: DomRepeatEvent<chrome.languageSettingsPrivate.Language>) { |
| const languageCode = e.model.item.code; |
| this.languageHelper_.setLanguageAlwaysTranslateState(languageCode, false); |
| this.languageSettingsMetricsProxy_.recordSettingsMetric( |
| LanguageSettingsActionType.REMOVE_FROM_ALWAYS_TRANSLATE); |
| } |
| |
| /** |
| * Stamps and opens the Add Languages dialog, registering a listener to |
| * disable the dialog's dom-if again on close. |
| */ |
| private onAddNeverTranslateLanguagesClick_(e: Event) { |
| e.preventDefault(); |
| const translatableLanguages = this.getTranslatableLanguages_(); |
| this.addLanguagesDialogLanguages_ = translatableLanguages.filter( |
| language => !this.languages!.neverTranslate.includes(language)); |
| this.showAddNeverTranslateDialog_ = true; |
| } |
| |
| private onNeverTranslateDialogClose_() { |
| this.showAddNeverTranslateDialog_ = false; |
| this.addLanguagesDialogLanguages_ = null; |
| const toFocus = |
| this.shadowRoot!.querySelector<HTMLElement>('#addNeverTranslate'); |
| assert(toFocus); |
| focusWithoutInk(toFocus); |
| } |
| |
| private onNeverTranslateLanguagesAdded_(e: CustomEvent<string[]>) { |
| const languagesToAdd = e.detail; |
| languagesToAdd.forEach(languageCode => { |
| this.languageHelper_.disableTranslateLanguage(languageCode); |
| this.languageSettingsMetricsProxy_.recordSettingsMetric( |
| LanguageSettingsActionType.ADD_TO_NEVER_TRANSLATE); |
| }); |
| } |
| |
| /** |
| * Removes a language from the never translate languages list. |
| */ |
| private onRemoveNeverTranslateLanguageClick_( |
| e: DomRepeatEvent<chrome.languageSettingsPrivate.Language>) { |
| const languageCode = e.model.item.code; |
| this.languageHelper_.enableTranslateLanguage(languageCode); |
| this.languageSettingsMetricsProxy_.recordSettingsMetric( |
| LanguageSettingsActionType.REMOVE_FROM_NEVER_TRANSLATE); |
| } |
| |
| private onTranslateToggleChange_(e: Event) { |
| this.languageSettingsMetricsProxy_.recordSettingsMetric( |
| (e.target as SettingsToggleButtonElement).checked ? |
| LanguageSettingsActionType.ENABLE_TRANSLATE_GLOBALLY : |
| LanguageSettingsActionType.DISABLE_TRANSLATE_GLOBALLY); |
| } |
| |
| /** |
| * @return Whether the list has any items. |
| */ |
| private hasSome_(list: any[]): boolean { |
| return !!list.length; |
| } |
| |
| /** |
| * @return Whether the list is has the given length. |
| */ |
| private hasLength_(list: any[], length: number): boolean { |
| return list.length === length; |
| } |
| |
| /** |
| * Gets the list of languages that chrome can translate |
| */ |
| private getTranslatableLanguages_(): |
| chrome.languageSettingsPrivate.Language[] { |
| return this.languages!.supported.filter(language => { |
| return this.isTranslateSupported_(language); |
| }); |
| } |
| |
| /** |
| * Filters only for translate supported languages |
| */ |
| private isTranslateSupported_( |
| language: chrome.languageSettingsPrivate.Language): boolean { |
| return isTranslateBaseLanguage(language); |
| } |
| } |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'settings-translate-page': SettingsTranslatePageElement; |
| } |
| } |
| |
| customElements.define( |
| SettingsTranslatePageElement.is, SettingsTranslatePageElement); |