Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/extensibility/ExtensionManagerView.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ define(function (require, exports, module) {

// Check if extension metadata contains localized content.
var lang = brackets.getLocale(),
shortLang = lang.split("-")[0];
shortLang = LocalizationUtils.shortLang(lang);
if (info.metadata["package-i18n"]) {
[shortLang, lang].forEach(function (locale) {
if (info.metadata["package-i18n"].hasOwnProperty(locale)) {
Expand Down
39 changes: 36 additions & 3 deletions src/utils/LocalizationUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define */
/*global define, brackets */

/**
* Utilities functions related to localization/i18n
Expand All @@ -31,7 +31,8 @@
define(function (require, exports, module) {
"use strict";

var Strings = require("strings");
var _ = require("thirdparty/lodash"),
Strings = require("strings");

/*
* Converts a language code to its written name, if possible.
Expand All @@ -47,7 +48,39 @@ define(function (require, exports, module) {
return i18n === undefined ? locale : i18n;
}

/*
* Returns the locale with the country part removed.
* Example: en-US -> en
*
* @param {string} locale The five-char or two-char language code. Defaults to brackets.getLocale()
* @return {string} The two-char language code with the country part removed
*/
function shortLang(locale) {
locale = locale || brackets.getLocale();
return locale.split("-")[0];
}

/*
* @return {Array} The users preferred languages, in order of priority
*/
function userLanguages() {
var locale = brackets.getLocale();
return _.uniq([locale, shortLang(locale)]);
}

/*
* @return {Array} The users preferred languages including English, in order of priority
*/
function languages() {
var locale = brackets.getLocale();
return _.uniq([locale, shortLang(locale), "en"]);
}


// Define public API
exports.getLocalizedLabel = getLocalizedLabel;
exports.shortLang = shortLang;
exports.userLanguages = userLanguages;
exports.languages = languages;

exports.getLocalizedLabel = getLocalizedLabel;
});
155 changes: 76 additions & 79 deletions src/utils/UpdateNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ define(function (require, exports, module) {
DefaultDialogs = require("widgets/DefaultDialogs"),
ExtensionManager = require("extensibility/ExtensionManager"),
PreferencesManager = require("preferences/PreferencesManager"),
LocalizationUtils = require("utils/LocalizationUtils"),
NativeApp = require("utils/NativeApp"),
Strings = require("strings"),
UpdateDialogTemplate = require("text!htmlContent/update-dialog.html"),
Expand Down Expand Up @@ -95,17 +96,9 @@ define(function (require, exports, module) {
/**
* Construct a new version update url with the given locale.
*
* @param {string=} locale - optional locale, defaults to 'brackets.getLocale()' when omitted.
* @param {boolean=} removeCountryPartOfLocale - optional, remove existing country information from locale 'en-gb' => 'en'
* return {string} the new version update url
*/
function _getVersionInfoUrl(locale, removeCountryPartOfLocale) {
locale = locale || brackets.getLocale();

if (removeCountryPartOfLocale) {
locale = locale.substring(0, 2);
}

function _getVersionInfoUrl(locale) {
return brackets.config.update_info_url + locale + ".json";
}

Expand All @@ -122,6 +115,48 @@ define(function (require, exports, module) {
* _versionInfoUrl is used for unit testing.
*/
function _getUpdateInformation(force, dontCache, _versionInfoUrl) {

// If the current locale isn't "en" or "en-US", check whether we actually have a
// locale-specific update notification, and fall back to "en" if not.
// Note: we check for both "en" and "en-US" to watch for the general case or
// country-specific English locale. The former appears default on Mac, while
// the latter appears default on Windows.
function loadLocalizedContent(langIndex, languages, lookupPromise) {
langIndex = langIndex || 0;
languages = languages || LocalizationUtils.languages();
lookupPromise = lookupPromise || new $.Deferred();
var lang = languages[langIndex],
localVersionInfoUrl;

if (lang) {
lang = lang.toLowerCase();
} else {
lookupPromise.reject();
}

if (langIndex === 0 && _versionInfoUrl) { // for unit tests
localVersionInfoUrl = _versionInfoUrl;
}
if (lang === "en" || lang === "en-us") {
localVersionInfoUrl = localVersionInfoUrl || _getVersionInfoUrl("en");
lookupPromise.resolve(localVersionInfoUrl);
} else {
localVersionInfoUrl = localVersionInfoUrl || _getVersionInfoUrl(lang);
$.ajax({
url: localVersionInfoUrl,
cache: false,
type: "HEAD"
})
.done(function () {
lookupPromise.resolve(localVersionInfoUrl);
})
.fail(function () {
loadLocalizedContent(langIndex + 1, languages, lookupPromise);
});
}
return lookupPromise.promise();
}

// Last time the versionInfoURL was fetched
var lastInfoURLFetchTime = PreferencesManager.getViewState("lastInfoURLFetchTime");

Expand All @@ -146,79 +181,41 @@ define(function (require, exports, module) {
}

if (fetchData) {
var lookupPromise = new $.Deferred(),
localVersionInfoUrl;

// If the current locale isn't "en" or "en-US", check whether we actually have a
// locale-specific update notification, and fall back to "en" if not.
// Note: we check for both "en" and "en-US" to watch for the general case or
// country-specific English locale. The former appears default on Mac, while
// the latter appears default on Windows.
var locale = brackets.getLocale().toLowerCase();
if (locale !== "en" && locale !== "en-us") {
localVersionInfoUrl = _versionInfoUrl || _getVersionInfoUrl();
$.ajax({
url: localVersionInfoUrl,
cache: false,
type: "HEAD"
}).fail(function (jqXHR, status, error) {
// get rid of any country information from locale and try again
var tmpUrl = _getVersionInfoUrl(brackets.getLocale(), true);
if (tmpUrl !== localVersionInfoUrl) {
$.ajax({
url: tmpUrl,
cache: false,
type: "HEAD"
}).fail(function (jqXHR, status, error) {
localVersionInfoUrl = _getVersionInfoUrl("en");
}).done(function (jqXHR, status, error) {
localVersionInfoUrl = tmpUrl;
}).always(function (jqXHR, status, error) {
lookupPromise.resolve();
});
} else {
localVersionInfoUrl = _getVersionInfoUrl("en");
lookupPromise.resolve();
}
}).done(function (jqXHR, status, error) {
lookupPromise.resolve();
});
} else {
localVersionInfoUrl = _versionInfoUrl || _getVersionInfoUrl("en");
lookupPromise.resolve();
}

lookupPromise.done(function () {
$.ajax({
url: localVersionInfoUrl,
dataType: "json",
cache: false
}).done(function (updateInfo, textStatus, jqXHR) {
if (!dontCache) {
lastInfoURLFetchTime = (new Date()).getTime();
PreferencesManager.setViewState("lastInfoURLFetchTime", lastInfoURLFetchTime);
PreferencesManager.setViewState("updateInfo", updateInfo);
}
result.resolve(updateInfo);
}).fail(function (jqXHR, status, error) {
// When loading data for unit tests, the error handler is
// called but the responseText is valid. Try to use it here,
// but *don't* save the results in prefs.
loadLocalizedContent()
.done(function (localVersionInfoUrl) {
$.ajax({
url: localVersionInfoUrl,
dataType: "json",
cache: false
}).done(function (updateInfo, textStatus, jqXHR) {
if (!dontCache) {
lastInfoURLFetchTime = (new Date()).getTime();
PreferencesManager.setViewState("lastInfoURLFetchTime", lastInfoURLFetchTime);
PreferencesManager.setViewState("updateInfo", updateInfo);
}
result.resolve(updateInfo);
}).fail(function (jqXHR, status, error) {
// When loading data for unit tests, the error handler is
// called but the responseText is valid. Try to use it here,
// but *don't* save the results in prefs.

if (!jqXHR.responseText) {
// Text is NULL or empty string, reject().
result.reject();
return;
}
if (!jqXHR.responseText) {
// Text is NULL or empty string, reject().
result.reject();
return;
}

try {
data = JSON.parse(jqXHR.responseText);
result.resolve(data);
} catch (e) {
result.reject();
}
try {
data = JSON.parse(jqXHR.responseText);
result.resolve(data);
} catch (e) {
result.reject();
}
});
})
.fail(function () {
result.reject();
});
});
} else {
result.resolve(data);
}
Expand Down