Commit 881f6a4c authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

Add apply i18n translation to CCA resolution menu

Bug: None
Change-Id: Ief14134de1d944229fede4e975f5f07c11c4eb6a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1631236Reviewed-by: default avatarSheng-hao Tsao <shenghao@chromium.org>
Commit-Queue: Kuo Jen Wei <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664385}
parent 78d37d78
...@@ -95,6 +95,10 @@ ...@@ -95,6 +95,10 @@
"message": "Timer duration", "message": "Timer duration",
"description": "Label for the button of timer-duration options." "description": "Label for the button of timer-duration options."
}, },
"CAMERA_RESOLUTION_BUTTON": {
"message": "Camera resolution",
"description": "Label for the button of camera resolution options."
},
"FEEDBACK_BUTTON": { "FEEDBACK_BUTTON": {
"message": "Send feedback", "message": "Send feedback",
"description": "Label for the feedback button." "description": "Label for the feedback button."
...@@ -131,6 +135,84 @@ ...@@ -131,6 +135,84 @@
"message": "10 seconds", "message": "10 seconds",
"description": "Label for timer-duration: 10 seconds." "description": "Label for timer-duration: 10 seconds."
}, },
"LABEL_PHOTO_RESOLUTION": {
"message": "($aspect_ratio_width$:$aspect_ratio_height$) $megapixel$ mega pixel",
"description": "Label for photo resolution options of specific resolution.",
"placeholders": {
"aspect_ratio_width": {
"content": "$1",
"example": "16"
},
"aspect_ratio_height": {
"content": "$2",
"example": "9"
},
"megapixel": {
"content": "$3",
"example": "0.9"
}
}
},
"LABEL_DETAIL_PHOTO_RESOLUTION": {
"message": "($aspect_ratio_width$:$aspect_ratio_height$ - $width$x$height$) $megapixel$ mega pixel",
"description": "Label for detail photo resolution options of specific resolution.",
"placeholders": {
"aspect_ratio_width": {
"content": "$1",
"example": "16"
},
"aspect_ratio_height": {
"content": "$2",
"example": "9"
},
"width": {
"content": "$3",
"example": "1920"
},
"height": {
"content": "$4",
"example": "1080"
},
"megapixel": {
"content": "$5",
"example": "0.9"
}
}
},
"LABEL_VIDEO_RESOLUTION": {
"message": "HD $height$p ($width$:$height$)",
"description": "Label for video resolution options of specific resolution.",
"placeholders": {
"height": {
"content": "$1",
"example": "720"
},
"width": {
"content": "$2",
"example": "1280"
}
}
},
"LABEL_FRONT_CAMERA": {
"message": "Front camera",
"description": "Label for front camera."
},
"LABEL_BACK_CAMERA": {
"message": "Back camera",
"description": "Label for back camera."
},
"LABEL_EXTERNAL_CAMERA": {
"message": "External camera",
"description": "Label for external camera."
},
"PHOTO_RESOLUTION_BUTTON": {
"message": "Photo resolution",
"description": "Label for the button of photo-resolution options."
},
"VIDEO_RESOLUTION_BUTTON": {
"message": "Video resolution",
"description": "Label for the button of video-resolution options."
},
"TAKE_PHOTO_BUTTON": { "TAKE_PHOTO_BUTTON": {
"message": "Take photo", "message": "Take photo",
"description": "Label for the shutter button to take photo." "description": "Label for the shutter button to take photo."
......
...@@ -50,7 +50,7 @@ cca.App = function() { ...@@ -50,7 +50,7 @@ cca.App = function() {
document.body.addEventListener('keydown', this.onKeyPressed_.bind(this)); document.body.addEventListener('keydown', this.onKeyPressed_.bind(this));
document.title = chrome.i18n.getMessage('name'); document.title = chrome.i18n.getMessage('name');
this.setupI18nElements_(); cca.util.setupI18nElements(document);
this.setupToggles_(); this.setupToggles_();
// Set up views navigation by their DOM z-order. // Set up views navigation by their DOM z-order.
...@@ -76,25 +76,6 @@ cca.App.useGalleryApp = function() { ...@@ -76,25 +76,6 @@ cca.App.useGalleryApp = function() {
return chrome.fileManagerPrivate && cca.state.get('ext-fs'); return chrome.fileManagerPrivate && cca.state.get('ext-fs');
}; };
/**
* Sets up i18n messages on elements by i18n attributes.
* @private
*/
cca.App.prototype.setupI18nElements_ = function() {
var getElements = (attr) => document.querySelectorAll('[' + attr + ']');
var getMessage = (element, attr) => chrome.i18n.getMessage(
element.getAttribute(attr));
var setAriaLabel = (element, attr) => element.setAttribute(
'aria-label', getMessage(element, attr));
getElements('i18n-content').forEach(
(element) => element.textContent = getMessage(element, 'i18n-content'));
getElements('i18n-aria').forEach(
(element) => setAriaLabel(element, 'i18n-aria'));
cca.tooltip.setup(getElements('i18n-label')).forEach(
(element) => setAriaLabel(element, 'i18n-label'));
};
/** /**
* Sets up toggles (checkbox and radio) by data attributes. * Sets up toggles (checkbox and radio) by data attributes.
* @private * @private
......
...@@ -866,3 +866,24 @@ cca.util.openHelp = function() { ...@@ -866,3 +866,24 @@ cca.util.openHelp = function() {
window.open( window.open(
'https://support.google.com/chromebook/?p=camera_usage_on_chromebook'); 'https://support.google.com/chromebook/?p=camera_usage_on_chromebook');
}; };
/*
* Sets up i18n messages on DOM subtree by i18n attributes.
* @param {HTMLElement} rootElement Root of DOM subtree to be set up with.
*/
cca.util.setupI18nElements = function(rootElement) {
var getElements = (attr) => rootElement.querySelectorAll('[' + attr + ']');
var getMessage = (element, attr) =>
chrome.i18n.getMessage(element.getAttribute(attr));
var setAriaLabel = (element, attr) =>
element.setAttribute('aria-label', getMessage(element, attr));
getElements('i18n-content')
.forEach(
(element) => element.textContent =
getMessage(element, 'i18n-content'));
getElements('i18n-aria')
.forEach((element) => setAriaLabel(element, 'i18n-aria'));
cca.tooltip.setup(getElements('i18n-label'))
.forEach((element) => setAriaLabel(element, 'i18n-label'));
};
...@@ -278,16 +278,24 @@ cca.views.ResolutionSettings.prototype = { ...@@ -278,16 +278,24 @@ cca.views.ResolutionSettings.prototype = {
* Template for generating option text from photo resolution width and height. * Template for generating option text from photo resolution width and height.
* @param {number} w Resolution width. * @param {number} w Resolution width.
* @param {number} h Resolution height. * @param {number} h Resolution height.
* @param {ResolList} resolutions All available resolutions.
* @return {string} Text shown on resolution option item. * @return {string} Text shown on resolution option item.
* @private * @private
*/ */
cca.views.ResolutionSettings.prototype.photoOptTextTempl_ = function(w, h) { cca.views.ResolutionSettings.prototype.photoOptTextTempl_ = function(
w, h, resolutions) {
const gcd = (a, b) => (a <= 0 ? b : gcd(b % a, a)); const gcd = (a, b) => (a <= 0 ? b : gcd(b % a, a));
if (h * w >= 100000) { const d = gcd(w, h);
return `${Math.round(w * h / 100000) / 10} megapixels (${w}:${h})`; const toMegapixel = (w, h) => Math.round(w * h / 100000) / 10;
if (resolutions.find(
([w2, h2]) => (w != w2 || h != h2) && w * h2 == w2 * h &&
toMegapixel(w, h) == toMegapixel(w2, h2))) {
return chrome.i18n.getMessage(
'label_detail_photo_resolution',
[w / d, h / d, w, h, toMegapixel(w, h)]);
} else { } else {
const d = gcd(w, h); return chrome.i18n.getMessage(
return `(${w / d}:${h / d}) ${w} x ${h}px`; 'label_photo_resolution', [w / d, h / d, toMegapixel(w, h)]);
} }
}; };
...@@ -299,13 +307,13 @@ cca.views.ResolutionSettings.prototype.photoOptTextTempl_ = function(w, h) { ...@@ -299,13 +307,13 @@ cca.views.ResolutionSettings.prototype.photoOptTextTempl_ = function(w, h) {
* @private * @private
*/ */
cca.views.ResolutionSettings.prototype.videoOptTextTempl_ = function(w, h) { cca.views.ResolutionSettings.prototype.videoOptTextTempl_ = function(w, h) {
return `HD ${h}p (${w}:${h})`; return chrome.i18n.getMessage('label_video_resolution', [h, w].map(String));
}; };
/** /**
* Finds resolution setting of target device id. * Finds photo and video resolution setting of target device id.
* @param {string} deviceId * @param {string} deviceId
* @return {?DeviceIdResols} * @return {?[DeviceIdResols, DeviceIdResols]}
* @private * @private
*/ */
cca.views.ResolutionSettings.prototype.getDeviceSetting_ = function(deviceId) { cca.views.ResolutionSettings.prototype.getDeviceSetting_ = function(deviceId) {
...@@ -343,7 +351,8 @@ cca.views.ResolutionSettings.prototype.updateResolutions_ = function() { ...@@ -343,7 +351,8 @@ cca.views.ResolutionSettings.prototype.updateResolutions_ = function() {
const prepItem = (item, [id, w, h, resolutions], optTextTempl) => { const prepItem = (item, [id, w, h, resolutions], optTextTempl) => {
item.dataset.deviceId = id; item.dataset.deviceId = id;
item.classList.toggle('multi-option', resolutions.length > 1); item.classList.toggle('multi-option', resolutions.length > 1);
item.querySelector('.description>span').textContent = optTextTempl(w, h); item.querySelector('.description>span').textContent =
optTextTempl(w, h, resolutions);
}; };
// Update front camera setting // Update front camera setting
...@@ -388,6 +397,7 @@ cca.views.ResolutionSettings.prototype.updateResolutions_ = function() { ...@@ -388,6 +397,7 @@ cca.views.ResolutionSettings.prototype.updateResolutions_ = function() {
const videoSetting = this.externalVideoSettings_[index]; const videoSetting = this.externalVideoSettings_[index];
if (deviceId !== focusedId) { if (deviceId !== focusedId) {
const extItem = document.importNode(this.extcamItemTempl_.content, true); const extItem = document.importNode(this.extcamItemTempl_.content, true);
cca.util.setupI18nElements(extItem);
var [titleItem, photoItem, videoItem] = var [titleItem, photoItem, videoItem] =
extItem.querySelectorAll('.menu-item'); extItem.querySelectorAll('.menu-item');
...@@ -396,11 +406,15 @@ cca.views.ResolutionSettings.prototype.updateResolutions_ = function() { ...@@ -396,11 +406,15 @@ cca.views.ResolutionSettings.prototype.updateResolutions_ = function() {
this.openPhotoResSettings_(photoSetting, photoItem); this.openPhotoResSettings_(photoSetting, photoItem);
} }
}); });
photoItem.setAttribute('aria-describedby', `${deviceId}-photores-desc`);
photoItem.querySelector('.description').id = `${deviceId}-photores-desc`;
videoItem.addEventListener('click', () => { videoItem.addEventListener('click', () => {
if (videoItem.classList.contains('multi-option')) { if (videoItem.classList.contains('multi-option')) {
this.openVideoResSettings_(videoSetting, videoItem); this.openVideoResSettings_(videoSetting, videoItem);
} }
}); });
videoItem.setAttribute('aria-describedby', `${deviceId}-videores-desc`);
videoItem.querySelector('.description').id = `${deviceId}-videores-desc`;
if (index < focusIdx) { if (index < focusIdx) {
this.resMenu_.insertBefore(extItem, fTitle); this.resMenu_.insertBefore(extItem, fTitle);
} else { } else {
...@@ -445,7 +459,7 @@ cca.views.ResolutionSettings.prototype.updateSelectedPhotoResolution_ = ...@@ -445,7 +459,7 @@ cca.views.ResolutionSettings.prototype.updateSelectedPhotoResolution_ =
`.menu-item[data-device-id="${deviceId}"]`)[1]; `.menu-item[data-device-id="${deviceId}"]`)[1];
} }
photoItem.querySelector('.description>span').textContent = photoItem.querySelector('.description>span').textContent =
this.photoOptTextTempl_(width, height); this.photoOptTextTempl_(width, height, photoSetting[3]);
// Update setting option if it's opened. // Update setting option if it's opened.
if (cca.state.get('photoresolutionsettings') && if (cca.state.get('photoresolutionsettings') &&
...@@ -528,7 +542,7 @@ cca.views.ResolutionSettings.prototype.openVideoResSettings_ = function( ...@@ -528,7 +542,7 @@ cca.views.ResolutionSettings.prototype.openVideoResSettings_ = function(
* Updates resolution menu with specified resolutions. * Updates resolution menu with specified resolutions.
* @param {HTMLElement} resolItem DOM element holding selected resolution. * @param {HTMLElement} resolItem DOM element holding selected resolution.
* @param {HTMLElement} menu Menu holding all resolution option elements. * @param {HTMLElement} menu Menu holding all resolution option elements.
* @param {function(number, number): string} optTextTempl Template * @param {function(number, number, ResolList): string} optTextTempl Template
* generating text content for each resolution option from its * generating text content for each resolution option from its
* width and height. * width and height.
* @param {function(number, number)} onChange Called when selected * @param {function(number, number)} onChange Called when selected
...@@ -548,15 +562,14 @@ cca.views.ResolutionSettings.prototype.updateMenu_ = function( ...@@ -548,15 +562,14 @@ cca.views.ResolutionSettings.prototype.updateMenu_ = function(
.forEach((element) => element.parentNode.removeChild(element)); .forEach((element) => element.parentNode.removeChild(element));
resolutions.forEach(([w, h], index) => { resolutions.forEach(([w, h], index) => {
// TODO(inker): i18n contents in optTextTempl
const item = document.importNode(this.resItemTempl_.content, true); const item = document.importNode(this.resItemTempl_.content, true);
const inputElement = item.querySelector('input'); const inputElement = item.querySelector('input');
item.querySelector('span').textContent = optTextTempl(w, h); item.querySelector('span').textContent = optTextTempl(w, h, resolutions);
inputElement.name = menu.dataset.name; inputElement.name = menu.dataset.name;
inputElement.dataset.width = w; inputElement.dataset.width = w;
inputElement.dataset.height = h; inputElement.dataset.height = h;
if (w == selectedWidth && h == selectedHeight) { if (w == selectedWidth && h == selectedHeight) {
captionText.textContent = optTextTempl(w, h); captionText.textContent = optTextTempl(w, h, resolutions);
inputElement.checked = true; inputElement.checked = true;
} }
inputElement.addEventListener('click', (event) => { inputElement.addEventListener('click', (event) => {
...@@ -566,7 +579,7 @@ cca.views.ResolutionSettings.prototype.updateMenu_ = function( ...@@ -566,7 +579,7 @@ cca.views.ResolutionSettings.prototype.updateMenu_ = function(
}); });
inputElement.addEventListener('change', (event) => { inputElement.addEventListener('change', (event) => {
if (inputElement.checked) { if (inputElement.checked) {
captionText.textContent = optTextTempl(w, h); captionText.textContent = optTextTempl(w, h, resolutions);
onChange(w, h); onChange(w, h);
} }
}); });
......
...@@ -170,6 +170,33 @@ ...@@ -170,6 +170,33 @@
<message desc="Label for for grid-type: 4x4." name="IDS_LABEL_GRID_4X4"> <message desc="Label for for grid-type: 4x4." name="IDS_LABEL_GRID_4X4">
4 x 4 4 x 4
</message> </message>
<message desc="Label for the button of camera-resolution options." name="IDS_CAMERA_RESOLUTION_BUTTON">
Camera resolution
</message>
<message desc="Label for the button of photo-resolution options." name="IDS_PHOTO_RESOLUTION_BUTTON">
Photo resolution
</message>
<message desc="Label for the button of video-resolution options." name="IDS_VIDEO_RESOLUTION_BUTTON">
Video resolution
</message>
<message desc="Label for front camera." name="IDS_LABEL_FRONT_CAMERA">
Front camera
</message>
<message desc="Label for back camera." name="IDS_LABEL_BACK_CAMERA">
Back camera
</message>
<message desc="Label for external camera." name="IDS_LABEL_EXTERNAL_CAMERA">
External camera
</message>
<message desc="Label for photo resolution options of specific resolution." name="IDS_LABEL_PHOTO_RESOLUTION">
(<ph name="aspect_ratio_width">$1<ex>16</ex></ph>:<ph name="aspect_ratio_height">$2<ex>9</ex></ph>) <ph name="megapixel">$3<ex>0.9</ex></ph> mega pixel
</message>
<message desc="Label for detail photo resolution options of specific resolution." name="IDS_LABEL_DETAIL_PHOTO_RESOLUTION">
(<ph name="aspect_ratio_width">$1<ex>16</ex></ph>:<ph name="aspect_ratio_height">$2<ex>9</ex></ph> - <ph name="width">$3<ex>1920</ex></ph>x<ph name="height">$4<ex>1080</ex></ph>) <ph name="megapixel">$5<ex>0.9</ex></ph> mega pixel
</message>
<message desc="Label for video resolution options of specific resolution." name="IDS_LABEL_VIDEO_RESOLUTION">
HD <ph name="height">$1<ex>720</ex></ph>p (<ph name="width">$2<ex>1280</ex></ph>:<ph name="height">$1<ex>720</ex></ph>)
</message>
<message desc="Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in." name="IDS_DELETE_CONFIRMATION_MSG"> <message desc="Confirmation message before removing a selected item from the gallery. Expects a file name to be passed in." name="IDS_DELETE_CONFIRMATION_MSG">
Do you really want to remove <ph name="file">$1<ex>IMG_20160520_000000.jpg</ex></ph>? Do you really want to remove <ph name="file">$1<ex>IMG_20160520_000000.jpg</ex></ph>?
</message> </message>
......
...@@ -180,14 +180,9 @@ ...@@ -180,14 +180,9 @@
</div> </div>
<div class="icon end"></div> <div class="icon end"></div>
</button> </button>
<button class="menu-item circle" id="settings-resolution" tabindex="0" <button class="menu-item circle" id="settings-resolution" tabindex="0">
aria-describedby="resolution-desc">
<div class="icon"></div> <div class="icon"></div>
<div> <div i18n-content="camera_resolution_button">
<div>Camera resolution</div>
<div class="description" id="resolution-desc" aria-hidden="true">
<span></span>
</div>
</div> </div>
<div class="icon end"></div> <div class="icon end"></div>
</button> </button>
...@@ -247,14 +242,15 @@ ...@@ -247,14 +242,15 @@
<div class="menu"> <div class="menu">
<div class="menu-header circle"> <div class="menu-header circle">
<button class="icon" tabindex="0" i18n-aria="back_button"></button> <button class="icon" tabindex="0" i18n-aria="back_button"></button>
<div>Camera resolutions</div> <div i18n-content="camera_resolution_button"></div>
</div> </div>
<div id="builtin-photo-header" class="menu-item">Photo</div> <div id="builtin-photo-header" class="menu-item"
i18n-content="label_switch_take_photo_button"></div>
<button class="menu-item resol-item circle" <button class="menu-item resol-item circle"
id="settings-front-photores" tabindex="0" id="settings-front-photores" tabindex="0"
aria-describedby="front-photores-desc"> aria-describedby="front-photores-desc">
<div> <div>
<div>Front camera</div> <div i18n-content="label_front_camera"></div>
<div class="description" id="front-photores-desc" <div class="description" id="front-photores-desc"
aria-hidden="true"> aria-hidden="true">
<span></span> <span></span>
...@@ -266,19 +262,20 @@ ...@@ -266,19 +262,20 @@
id="settings-back-photores" tabindex="0" id="settings-back-photores" tabindex="0"
aria-describedby="back-photores-desc"> aria-describedby="back-photores-desc">
<div> <div>
<div>Back camera</div> <div i18n-content="label_back_camera"></div>
<div class="description" id="back-photores-desc" aria-hidden="true"> <div class="description" id="back-photores-desc" aria-hidden="true">
<span></span> <span></span>
</div> </div>
</div> </div>
<div class="icon end"></div> <div class="icon end"></div>
</button> </button>
<div id="builtin-video-header" class="menu-item">Video</div> <div id="builtin-video-header" class="menu-item"
i18n-content="label_switch_record_video_button"></div>
<button class="menu-item resol-item circle" <button class="menu-item resol-item circle"
id="settings-front-videores" tabindex="0" id="settings-front-videores" tabindex="0"
aria-describedby="front-videores-desc"> aria-describedby="front-videores-desc">
<div> <div>
<div>Front camera</div> <div i18n-content="label_front_camera"></div>
<div class="description" id="front-videores-desc" aria-hidden="true"> <div class="description" id="front-videores-desc" aria-hidden="true">
<span></span> <span></span>
</div> </div>
...@@ -289,7 +286,7 @@ ...@@ -289,7 +286,7 @@
id="settings-back-videores" tabindex="0" id="settings-back-videores" tabindex="0"
aria-describedby="back-videores-desc"> aria-describedby="back-videores-desc">
<div> <div>
<div>Back camera</div> <div i18n-content="label_back_camera"></div>
<div class="description" id="back-videores-desc" aria-hidden="true"> <div class="description" id="back-videores-desc" aria-hidden="true">
<span></span> <span></span>
</div> </div>
...@@ -302,7 +299,7 @@ ...@@ -302,7 +299,7 @@
<div class="menu" data-name="photores"> <div class="menu" data-name="photores">
<div class="menu-header circle"> <div class="menu-header circle">
<button class="icon" tabindex="0" i18n-aria="back_button"></button> <button class="icon" tabindex="0" i18n-aria="back_button"></button>
<div>Photo resolution</div> <div i18n-content="photo_resolution_button"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -310,7 +307,7 @@ ...@@ -310,7 +307,7 @@
<div class="menu" data-name="videores"> <div class="menu" data-name="videores">
<div class="menu-header circle"> <div class="menu-header circle">
<button class="icon" tabindex="0" i18n-aria="back_button"></button> <button class="icon" tabindex="0" i18n-aria="back_button"></button>
<div>Video resolution</div> <div i18n-content="video_resolution_button"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -358,11 +355,12 @@ ...@@ -358,11 +355,12 @@
</label> </label>
</template> </template>
<template id="extcam-resolution-item-template"> <template id="extcam-resolution-item-template">
<div class="menu-item external-camera">External camera</div> <div class="menu-item external-camera"
i18n-content="label_external_camera"></div>
<button class="menu-item resol-item external-camera" <button class="menu-item resol-item external-camera"
tabindex="0"> tabindex="0">
<div> <div>
<div>Photo resolution</div> <div i18n-content="photo_resolution_button"></div>
<div class="description" aria-hidden="true"> <div class="description" aria-hidden="true">
<span></span> <span></span>
</div> </div>
...@@ -372,7 +370,7 @@ ...@@ -372,7 +370,7 @@
<button class="menu-item resol-item circle external-camera" <button class="menu-item resol-item circle external-camera"
tabindex="0"> tabindex="0">
<div> <div>
<div>Video resolution</div> <div i18n-content="video_resolution_button"></div>
<div class="description" aria-hidden="true"> <div class="description" aria-hidden="true">
<span></span> <span></span>
</div> </div>
......
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