Skip to content

Commit 2d692ab

Browse files
Googlerchanning-google
authored andcommitted
Updated FirebaseUI for Web:
- Fixes for internationalization GitOrigin-RevId=1539e6c73a85870846b1aa84ffc5cbc214605783 Change-Id: I6fae6c918d269944df7831e2ea1ec9d845ffe829
1 parent 1539e6c commit 2d692ab

File tree

10 files changed

+157
-52
lines changed

10 files changed

+157
-52
lines changed

LANGUAGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@
4343
| th | Thai |
4444
| tr | Turkish |
4545
| uk | Ukrainian |
46-
| vi | Vietnamese |
46+
| vi | Vietnamese |

buildtools/country_data/generate_country_data.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ cp "$SPRITE_DIR/flags.css" "$OUT_DIR"
4848

4949
# Generate the country data JS.
5050
./filter_country_data.js > "$OUT_DIR/country_data.js"
51+
52+
# Generate the country data Markdown.
53+
./make_country_list_for_readme.js > "$OUT_DIR/country_data.md"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env node
2+
/*
3+
* Copyright 2016 Google Inc. All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License. You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software distributed under the
11+
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
/*
17+
* Converts the data in full_country_data to a Markdown table.
18+
*
19+
* Usage:
20+
* It is recommended to just run generate_country_data.sh. However, you can run
21+
* this on its own with:
22+
* $ ./make_country_list_for_readme.js
23+
*
24+
* Then, take the output and put it between the START COPIED TABLE and END
25+
* COPIED TABLE markers in javascript/data/README.md.
26+
*/
27+
28+
var fullCountryData = require('./full_country_data.json');
29+
30+
// Keep track of seen country codes to eliminate duplicates.
31+
var seenCountryCodes = {};
32+
33+
// Print the table header.
34+
console.log('| Code | Country |');
35+
console.log('| ---- | ------- |');
36+
37+
for (var i = 0; i < fullCountryData.length; i++) {
38+
var country = fullCountryData[i];
39+
40+
// Don't print duplicate entries.
41+
if (seenCountryCodes[country.iso2_cc]) {
42+
continue;
43+
}
44+
seenCountryCodes[country.iso2_cc] = true;
45+
46+
// Replace square brackets with parentheses, for Markdown support.
47+
var normalizedName = country.name.replace(/\[/g, '(').replace(/\]/g, ')');
48+
49+
// Print the Markdown table row.
50+
console.log('| ' + country.iso2_cc + ' | ' + normalizedName + ' |');
51+
}

javascript/data/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Valid country codes to pass in to `defaultCountry` for phone number
44
authentication:
55

6+
<!-- START COPIED TABLE -->
67
| Code | Country |
78
| ---- | ------- |
89
| AF | Afghanistan |
@@ -251,3 +252,4 @@ authentication:
251252
| YE | Yemen |
252253
| ZM | Zambia |
253254
| ZW | Zimbabwe |
255+
<!-- END COPIED TABLE -->

javascript/widgets/authui.js

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -218,25 +218,7 @@ firebaseui.auth.AuthUI.prototype.isPending = function() {
218218
*/
219219
firebaseui.auth.AuthUI.prototype.start = function(element, config) {
220220
var self = this;
221-
var onReady = function() {
222-
var resetWarning = 'UI Widget is already rendered on the page and is pen' +
223-
'ding some user interaction. Only one widget instance can be rendere' +
224-
'd per page. The previous instance has been automatically reset.';
225-
// Only one auth instance can be rendered per page. This is because
226-
// accountchooser.com callbacks are set once to the AuthUI instance that
227-
// first calls them.
228-
if (firebaseui.auth.AuthUI.widgetAuthUi_) {
229-
// Already rendered, automatically reset.
230-
// First check if there is a pending operation on that widget, if so,
231-
// log a reset warning to the console.
232-
if (firebaseui.auth.AuthUI.widgetAuthUi_.isPending()) {
233-
firebaseui.auth.log.warning(resetWarning);
234-
}
235-
firebaseui.auth.AuthUI.widgetAuthUi_.reset();
236-
}
237-
// Set widget AuthUI as current instance.
238-
firebaseui.auth.AuthUI.widgetAuthUi_ = self;
239-
};
221+
240222
// There is a problem when config in second call modifies accountchooser.com
241223
// related config. eg. acUiConfig
242224
// These changes will be ignored as only the first accountchooser.com related
@@ -247,31 +229,61 @@ firebaseui.auth.AuthUI.prototype.start = function(element, config) {
247229
// Wrap it in a onload callback to wait for the DOM element is rendered.
248230
// If document already loaded, render immediately.
249231
if (doc.readyState == 'complete') {
250-
// Confirm element exists.
251-
var container = firebaseui.auth.util.getElement(
252-
element, firebaseui.auth.AuthUI.ELEMENT_NOT_FOUND_);
253-
onReady();
254-
self.widgetElement_ = container;
255-
// Initialize widget page change listener.
256-
self.initPageChangeListener_(container);
257-
// Document already loaded, render on demand.
258-
firebaseui.auth.widget.dispatcher.dispatchOperation(self, element);
232+
this.initElement_(element);
259233
} else {
260234
// Document not ready, wait for load before rendering.
261235
goog.events.listenOnce(window, goog.events.EventType.LOAD, function() {
262-
// Confirm element exists.
263-
var container = firebaseui.auth.util.getElement(
264-
element, firebaseui.auth.AuthUI.ELEMENT_NOT_FOUND_);
265-
onReady();
266-
self.widgetElement_ = container;
267-
// Initialize widget page change listener.
268-
self.initPageChangeListener_(container);
269-
firebaseui.auth.widget.dispatcher.dispatchOperation(self, element);
236+
self.initElement_(element);
270237
});
271238
}
272239
};
273240

274241

242+
/**
243+
* Initializes the FirebaseUI element.
244+
* @param {string|!Element} element The container element or the query selector.
245+
* @private
246+
*/
247+
firebaseui.auth.AuthUI.prototype.initElement_ = function(element) {
248+
// Confirm element exists.
249+
var container = firebaseui.auth.util.getElement(
250+
element, firebaseui.auth.AuthUI.ELEMENT_NOT_FOUND_);
251+
252+
// Set the "lang" attribute; without this, there are subtle rendering errors
253+
// like vowel capitalization in Turkish.
254+
255+
// Make sure the locale uses hyphens instead of strings.
256+
var locale = goog.LOCALE.replace(/_/g, '-');
257+
container.setAttribute('lang', locale);
258+
259+
// Only one auth instance can be rendered per page. This is because
260+
// accountchooser.com callbacks are set once to the AuthUI instance that
261+
// first calls them.
262+
if (firebaseui.auth.AuthUI.widgetAuthUi_) {
263+
// Already rendered, automatically reset.
264+
// First check if there is a pending operation on that widget, if so,
265+
// log a reset warning to the console.
266+
if (firebaseui.auth.AuthUI.widgetAuthUi_.isPending()) {
267+
var resetWarning = 'UI Widget is already rendered on the page and is ' +
268+
'pending some user interaction. Only one widget instance can be ' +
269+
'rendered per page. The previous instance has been automatically ' +
270+
'reset.';
271+
firebaseui.auth.log.warning(resetWarning);
272+
}
273+
firebaseui.auth.AuthUI.widgetAuthUi_.reset();
274+
}
275+
276+
// Set widget AuthUI as current instance.
277+
firebaseui.auth.AuthUI.widgetAuthUi_ = this;
278+
279+
this.widgetElement_ = container;
280+
// Initialize widget page change listener.
281+
this.initPageChangeListener_(container);
282+
// Document already loaded, render on demand.
283+
firebaseui.auth.widget.dispatcher.dispatchOperation(this, element);
284+
};
285+
286+
275287
/**
276288
* Registers a pending promise or reset function.
277289
* @param {?goog.Promise|?firebase.Promise|?function()} p The pending promise.
@@ -304,6 +316,11 @@ firebaseui.auth.AuthUI.prototype.getAuthUiGetter = function() {
304316

305317
/** Reset rendered widget and removes it from display. */
306318
firebaseui.auth.AuthUI.prototype.reset = function() {
319+
// Remove the "lang" attribute that we set in start().
320+
if (this.widgetElement_) {
321+
this.widgetElement_.removeAttribute('lang');
322+
}
323+
307324
// After reset, if the sign-in widget callback is called again, it should not
308325
// resolve with the previous redirect result.
309326
this.getRedirectResult_ =

javascript/widgets/authui_test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,28 @@ function testStart() {
394394
}
395395

396396

397+
function testSetLang() {
398+
testStubs.replace(goog, 'LOCALE', 'de');
399+
app1.start(container1, config1);
400+
assertEquals('de', container1.getAttribute('lang'));
401+
app1.reset();
402+
assertFalse(container1.hasAttribute('lang'));
403+
404+
testStubs.replace(goog, 'LOCALE', 'zh-CN');
405+
app1.start(container1, config1);
406+
assertEquals('zh-CN', container1.getAttribute('lang'));
407+
app1.reset();
408+
assertFalse(container1.hasAttribute('lang'));
409+
410+
testStubs.replace(goog, 'LOCALE', 'zh_CN');
411+
app1.start(container1, config1);
412+
// The lang should have a dash instead of an underscore.
413+
assertEquals('zh-CN', container1.getAttribute('lang'));
414+
app1.reset();
415+
assertFalse(container1.hasAttribute('lang'));
416+
}
417+
418+
397419
function testStart_elementNotFound() {
398420
// Test widget start method with missing element.
399421
// Test correct error message thrown when widget element not found.

javascript/widgets/handler/common.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ goog.require('firebaseui.auth.widget.handler');
3939
goog.require('goog.Promise');
4040

4141
goog.require('goog.array');
42+
goog.require('goog.html.TrustedResourceUrl');
4243
goog.require('goog.net.jsloader');
44+
goog.require('goog.string.Const');
4345

4446
goog.forwardDeclare('firebaseui.auth.AuthUI');
4547

@@ -97,8 +99,10 @@ firebaseui.auth.widget.handler.common.loadAccountchooserJs = function(
9799
if (typeof accountchooser == 'undefined' &&
98100
firebaseui.auth.sni.isSupported()) {
99101
// Not yet loaded but supported.
102+
var src = goog.html.TrustedResourceUrl.fromConstant(
103+
goog.string.Const.from(ACCOUNTCHOOSER_SRC));
100104
firebaseui.auth.widget.handler.common.acLoader_ = goog.Promise.resolve(
101-
goog.net.jsloader.load(ACCOUNTCHOOSER_SRC)).thenCatch(function() {});
105+
goog.net.jsloader.safeLoad(src)).thenCatch(function() {});
102106
} else {
103107
// Either not supported by the browser or externally loaded.
104108
firebaseui.auth.widget.handler.common.acLoader_ = goog.Promise.resolve();

protractor_spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ describe('Run all Closure unit tests', function() {
6060
* Runs the test routines for a given test path and retries up to a
6161
* certain number of times on timeout.
6262
* @param {number} tries The number of times to retry on timeout.
63-
* @param {function} done The function to run on completion.
63+
* @param {function()} done The function to run on completion.
6464
*/
6565
var runRoutine = function(tries, done) {
6666
browser.navigate()

soy/pages.soy

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@
6060
{call firebaseui.auth.soy2.element.password /}
6161
</div>
6262
<div class="firebaseui-card-actions">
63+
<div class="firebaseui-form-links">
64+
{call firebaseui.auth.soy2.element.passwordRecoveryButton /}
65+
</div>
6366
<div class="firebaseui-form-actions">
6467
{call firebaseui.auth.soy2.element.signInButton /}
6568
</div>
66-
{call firebaseui.auth.soy2.element.passwordRecoveryButton /}
6769
</div>
6870
</form>
6971
</div>
@@ -228,7 +230,9 @@
228230
{call firebaseui.auth.soy2.element.password /}
229231
</div>
230232
<div class="firebaseui-card-actions">
231-
{call firebaseui.auth.soy2.element.passwordRecoveryButton /}
233+
<div class="firebaseui-form-links">
234+
{call firebaseui.auth.soy2.element.passwordRecoveryButton /}
235+
</div>
232236
<div class="firebaseui-form-actions">
233237
{call firebaseui.auth.soy2.element.signInButton /}
234238
</div>

stylesheet/firebase-ui.css

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,24 @@
4646
}
4747

4848
.firebaseui-card-actions {
49+
display: table;
4950
font-size: 14px;
50-
line-height: 36px;
5151
padding: 8px 24px 24px 24px;
5252
text-align: left;
53+
width: 100%;
5354
}
5455

55-
/* Clearfix */
56-
.firebaseui-card-actions::after {
57-
clear: both;
58-
content: "";
59-
display: table;
56+
.firebaseui-form-links {
57+
display: table-cell;
58+
vertical-align: middle;
59+
width: 100%;
60+
}
61+
62+
.firebaseui-form-actions {
63+
display: table-cell;
64+
text-align: right;
65+
white-space: nowrap;
66+
width: 100%;
6067
}
6168

6269
.firebaseui-title,
@@ -197,11 +204,6 @@ input.firebaseui-input-invalid{
197204
text-decoration: underline;
198205
}
199206

200-
.firebaseui-form-actions {
201-
direction: ltr;
202-
float: right;
203-
}
204-
205207
.firebaseui-indent {
206208
margin-left: 1em;
207209
}

0 commit comments

Comments
 (0)