Bug 1476079 - Add onboarding focus, funneling metrics and bug fixes to Activity Stream. r=ursula

MozReview-Commit-ID: 66sjBl8LBQu

--HG--
extra : rebase_source : c6b3ecf1e011e2a98aa3c4612b19c90868bbefb0
This commit is contained in:
Ed Lee 2018-07-16 13:38:58 -07:00
Родитель 826bfa5d74
Коммит 2d63e9e89f
44 изменённых файлов: 508 добавлений и 421 удалений

Просмотреть файл

@ -0,0 +1,111 @@
exports.DEFAULT_LOCALE = "en-US";
// This locales list is to find any similar locales that we can reuse strings
// instead of falling back to the default, e.g., use bn-BD strings for bn-IN.
// https://hg.mozilla.org/mozilla-central/file/tip/browser/locales/l10n.toml
exports.CENTRAL_LOCALES = [
"ach",
"af",
"an",
"ar",
"as",
"ast",
"az",
"be",
"bg",
"bn-BD",
"bn-IN",
"br",
"bs",
"ca",
"cak",
"crh",
"cs",
"cy",
"da",
"de",
"dsb",
"el",
"en-CA",
"en-GB",
"en-ZA",
"eo",
"es-AR",
"es-CL",
"es-ES",
"es-MX",
"et",
"eu",
"fa",
"ff",
"fi",
"fr",
"fy-NL",
"ga-IE",
"gd",
"gl",
"gn",
"gu-IN",
"he",
"hi-IN",
"hr",
"hsb",
"hu",
"hy-AM",
"ia",
"id",
"is",
"it",
"ja",
"ja-JP-mac",
"ka",
"kab",
"kk",
"km",
"kn",
"ko",
"lij",
"lo",
"lt",
"ltg",
"lv",
"mai",
"mk",
"ml",
"mr",
"ms",
"my",
"nb-NO",
"ne-NP",
"nl",
"nn-NO",
"oc",
"or",
"pa-IN",
"pl",
"pt-BR",
"pt-PT",
"rm",
"ro",
"ru",
"si",
"sk",
"sl",
"son",
"sq",
"sr",
"sv-SE",
"ta",
"te",
"th",
"tl",
"tr",
"uk",
"ur",
"uz",
"vi",
"wo",
"xh",
"zh-CN",
"zh-TW"
];

Просмотреть файл

@ -6,7 +6,7 @@ const path = require("path");
// Note: this file is generated by webpack from content-src/activity-stream-prerender.jsx // Note: this file is generated by webpack from content-src/activity-stream-prerender.jsx
const {prerender} = require("./prerender"); const {prerender} = require("./prerender");
const DEFAULT_LOCALE = "en-US"; const {CENTRAL_LOCALES, DEFAULT_LOCALE} = require("./locales");
// Note: DEFAULT_OPTIONS.baseUrl should match BASE_URL in aboutNewTabService.js // Note: DEFAULT_OPTIONS.baseUrl should match BASE_URL in aboutNewTabService.js
// in mozilla-central. // in mozilla-central.
@ -15,116 +15,6 @@ const DEFAULT_OPTIONS = {
baseUrl: "resource://activity-stream/" baseUrl: "resource://activity-stream/"
}; };
// This locales list is to find any similar locales that we can reuse strings
// instead of falling back to the default, e.g., use bn-BD strings for bn-IN.
// https://hg.mozilla.org/mozilla-central/file/tip/browser/locales/l10n.toml
const CENTRAL_LOCALES = [
"ach",
"af",
"an",
"ar",
"as",
"ast",
"az",
"be",
"bg",
"bn-BD",
"bn-IN",
"br",
"bs",
"ca",
"cak",
"crh",
"cs",
"cy",
"da",
"de",
"dsb",
"el",
"en-CA",
"en-GB",
"en-ZA",
"eo",
"es-AR",
"es-CL",
"es-ES",
"es-MX",
"et",
"eu",
"fa",
"ff",
"fi",
"fr",
"fy-NL",
"ga-IE",
"gd",
"gl",
"gn",
"gu-IN",
"he",
"hi-IN",
"hr",
"hsb",
"hu",
"hy-AM",
"ia",
"id",
"is",
"it",
"ja",
"ja-JP-mac",
"ka",
"kab",
"kk",
"km",
"kn",
"ko",
"lij",
"lo",
"lt",
"ltg",
"lv",
"mai",
"mk",
"ml",
"mr",
"ms",
"my",
"nb-NO",
"ne-NP",
"nl",
"nn-NO",
"oc",
"or",
"pa-IN",
"pl",
"pt-BR",
"pt-PT",
"rm",
"ro",
"ru",
"si",
"sk",
"sl",
"son",
"sq",
"sr",
"sv-SE",
"ta",
"te",
"th",
"tl",
"tr",
"uk",
"ur",
"uz",
"vi",
"wo",
"xh",
"zh-CN",
"zh-TW"
];
// Locales that should be displayed RTL // Locales that should be displayed RTL
const RTL_LIST = ["ar", "he", "fa", "ur"]; const RTL_LIST = ["ar", "he", "fa", "ur"];

Просмотреть файл

@ -7,7 +7,7 @@ const fetch = require("node-fetch");
/* globals cd, ls, mkdir, rm, ShellString */ /* globals cd, ls, mkdir, rm, ShellString */
require("shelljs/global"); require("shelljs/global");
const DEFAULT_LOCALE = "en-US"; const {CENTRAL_LOCALES, DEFAULT_LOCALE} = require("./locales");
const L10N_CENTRAL = "https://hg.mozilla.org/l10n-central"; const L10N_CENTRAL = "https://hg.mozilla.org/l10n-central";
const PROPERTIES_PATH = "raw-file/default/browser/chrome/browser/activity-stream/newtab.properties"; const PROPERTIES_PATH = "raw-file/default/browser/chrome/browser/activity-stream/newtab.properties";
const STRINGS_FILE = "strings.properties"; const STRINGS_FILE = "strings.properties";
@ -16,16 +16,21 @@ const STRINGS_FILE = "strings.properties";
async function getLocales() { async function getLocales() {
console.log(`Getting locales from ${L10N_CENTRAL}`); console.log(`Getting locales from ${L10N_CENTRAL}`);
// Add all non-test sub repository locales // Add sub repository locales that mozilla-central builds
const locales = []; const locales = [];
const unbuilt = [];
const subrepos = await (await fetch(`${L10N_CENTRAL}?style=json`)).json(); const subrepos = await (await fetch(`${L10N_CENTRAL}?style=json`)).json();
subrepos.entries.forEach(({name}) => { subrepos.entries.forEach(({name}) => {
if (name !== "x-testing") { if (CENTRAL_LOCALES.includes(name)) {
locales.push(name); locales.push(name);
} else {
unbuilt.push(name);
} }
}); });
console.log(`Got ${locales.length} locales: ${locales}`); console.log(`Got ${locales.length} mozilla-central locales: ${locales}`);
console.log(`Skipped ${unbuilt.length} unbuilt locales: ${unbuilt}`);
return locales; return locales;
} }
@ -62,9 +67,17 @@ async function updateLocales() {
} }
}); });
// Save the properties file for each locale in parallel // Save the properties file for each locale one at a time to avoid too many
const locales = await getLocales(); // parallel connections (resulting in ECONNRESET / socket hang up)
const missing = (await Promise.all(locales.map(saveProperties))).filter(v => v); const missing = [];
for (const locale of await getLocales()) {
process.stdout.write(`${locale} `);
if (await saveProperties(locale)) {
missing.push(locale);
}
}
console.log("");
console.log(`Skipped ${missing.length} locales without strings: ${missing.sort()}`); console.log(`Skipped ${missing.length} locales without strings: ${missing.sort()}`);
console.log(` console.log(`

Просмотреть файл

@ -21,7 +21,7 @@ export class ModalOverlay extends React.PureComponent {
<h2> {title} </h2> <h2> {title} </h2>
{this.props.children} {this.props.children}
<div className="footer"> <div className="footer">
<button onClick={this.props.onDoneButton} className="button primary modalButton"> {button_label} </button> <button tabIndex="2" onClick={this.props.onDoneButton} className="button primary modalButton"> {button_label} </button>
</div> </div>
</div> </div>
</div> </div>

Просмотреть файл

@ -99,6 +99,12 @@
height: 30px; height: 30px;
padding: 4px 0 6px; padding: 4px 0 6px;
font-size: 15px; font-size: 15px;
&:focus,
&.active {
box-shadow: $shadow-primary;
transition: box-shadow 150ms;
}
} }
} }
} }

Просмотреть файл

@ -8,7 +8,7 @@ Field name | Type | Required | Description | Example / Note
`publish_end` | `date` | No | When to stop showing the message | `1524474850876` `publish_end` | `date` | No | When to stop showing the message | `1524474850876`
`content` | `object` | Yes | An object containing all variables/props to be rendered in the template. Subset of allowed tags detailed below. | [See example below](#html-subset) `content` | `object` | Yes | An object containing all variables/props to be rendered in the template. Subset of allowed tags detailed below. | [See example below](#html-subset)
`campaign` | `string` | No | Campaign id that the message belongs to | `RustWebAssembly` `campaign` | `string` | No | Campaign id that the message belongs to | `RustWebAssembly`
`targeting` | `string` `JEXL` | No | A [JEXL expression](http://normandy.readthedocs.io/en/latest/user/filter_expressions.html#jexl-basics) with all targeting information needed in order to decide if the message is shown | Not yet implemented, [some examples](http://normandy.readthedocs.io/en/latest/user/filter_expressions.html#examples) `targeting` | `string` `JEXL` | No | A [JEXL expression](http://normandy.readthedocs.io/en/latest/user/filter_expressions.html#jexl-basics) with all targeting information needed in order to decide if the message is shown | Not yet implemented, [Examples](#targeting-attributes)
`trigger` | `string` | No | An event or condition upon which the message will be immediately shown. This can be combined with `targeting`. Messages that define a trigger will not be shown during non-trigger-based passive message rotation. `trigger` | `string` | No | An event or condition upon which the message will be immediately shown. This can be combined with `targeting`. Messages that define a trigger will not be shown during non-trigger-based passive message rotation.
### Message example ### Message example
@ -43,3 +43,62 @@ Links cannot be rendered using regular anchor tags because [Fluent does not allo
If a tag that is not on the allowed is used, the text content will be extracted and displayed. If a tag that is not on the allowed is used, the text content will be extracted and displayed.
Grouping multiple allowed elements is not possible, only the first level will be used: `<u><b>text</b></u>` will be interpreted as `<u>text</u>`. Grouping multiple allowed elements is not possible, only the first level will be used: `<u><b>text</b></u>` will be interpreted as `<u>text</u>`.
### Targeting attributes
For a more in-depth explanation of JEXL syntax you can read the [Normady project docs](https://normandy.readthedocs.io/en/stable/user/filters.html#jexl-basics).
Currently we expose the following targeting attributes that can be used by messages:
Name | Type | Example value | Description
--- | --- | --- | ---
`profileAgeCreated` | Number | `1522843725924` | Profile creation timestamp
`profileAgeReset` | `Number` or `undefined` | `1522843725924` | When (if) the profile was reset
`hasFxAccount` | `Boolean` | `true` | Does the user have a firefox account
`addonsInfo` | `Object` | [example below](#addonsinfo-example) | Information about the addons the user has installed
#### addonsInfo Example
```javascript
{
"addons": {
...
"activity-stream@mozilla.org": {
"version": "2018.07.06.1113-783442c0",
"type": "extension",
"isSystem": true,
"isWebExtension": false,
"name": "Activity Stream",
"userDisabled": false,
"installDate": "2018-03-10T03:41:06.000Z"
}
},
"isFullData": true
}
```
#### Usage
A message needs to contain the `targeting` property (JEXL string) which is evaluated against the provided attributes.
Examples:
```javascript
{
"id": "7864",
"content": {...},
// simple equality check
"targeting": "hasFxAccount == true"
}
{
"id": "7865",
"content": {...},
// using JEXL transforms and combining two attributes
"targeting": "hasFxAccount == true && profileAgeCreated > '2018-01-07'|date"
}
{
"id": "7866",
"content": {...},
// targeting addon information
"targeting": "addonsInfo.addons['activity-stream@mozilla.org'].name == 'Activity Stream'"
}
```

Просмотреть файл

@ -24,7 +24,7 @@ class OnboardingCard extends React.PureComponent {
<p> {content.text} </p> <p> {content.text} </p>
</span> </span>
<span> <span>
<button className="button onboardingButton" onClick={this.onClick}> {content.button_label} </button> <button tabIndex="1" className="button onboardingButton" onClick={this.onClick}> {content.button_label} </button>
</span> </span>
</div> </div>
</div> </div>

Просмотреть файл

@ -131,6 +131,12 @@
float: none; float: none;
margin-top: 30px; margin-top: 30px;
} }
&:focus,
&.active {
box-shadow: $shadow-primary;
transition: box-shadow 150ms;
}
} }

Просмотреть файл

@ -1,5 +1,5 @@
import {actionCreators as ac, actionTypes as at} from "common/Actions.jsm";
import {FormattedMessage, injectIntl} from "react-intl"; import {FormattedMessage, injectIntl} from "react-intl";
import {actionCreators as ac} from "common/Actions.jsm";
import {connect} from "react-redux"; import {connect} from "react-redux";
import React from "react"; import React from "react";
@ -15,8 +15,29 @@ export class _StartupOverlay extends React.PureComponent {
this.state = { this.state = {
emailInput: "", emailInput: "",
overlayRemoved: false overlayRemoved: false,
flowId: "",
flowBeginTime: 0
}; };
this.didFetch = false;
}
async componentWillUpdate() {
if (this.props.fxa_endpoint && !this.didFetch) {
try {
this.didFetch = true;
const response = await fetch(`${this.props.fxa_endpoint}/metrics-flow`);
if (response.status === 200) {
const {flowId, flowBeginTime} = await response.json();
this.setState({flowId, flowBeginTime});
}
} catch (error) {
this.props.dispatch(ac.OnlyToMain({type: at.TELEMETRY_UNDESIRED_EVENT, data: {value: "FXA_METRICS_ERROR"}}));
}
}
}
componentDidMount() {
this.initScene(); this.initScene();
} }
@ -71,8 +92,9 @@ export class _StartupOverlay extends React.PureComponent {
return null; return null;
} }
let termsLink = (<a href="https://accounts.firefox.com/legal/terms" target="_blank" rel="noopener noreferrer"><FormattedMessage id="firstrun_terms_of_service" /></a>); let termsLink = (<a href={`${this.props.fxa_endpoint}/legal/terms`} target="_blank" rel="noopener noreferrer"><FormattedMessage id="firstrun_terms_of_service" /></a>);
let privacyLink = (<a href="https://accounts.firefox.com/legal/privacy" target="_blank" rel="noopener noreferrer"><FormattedMessage id="firstrun_privacy_notice" /></a>); let privacyLink = (<a href={`${this.props.fxa_endpoint}/legal/privacy`} target="_blank" rel="noopener noreferrer"><FormattedMessage id="firstrun_privacy_notice" /></a>);
return ( return (
<div className={`overlay-wrapper ${this.state.show ? "show" : ""}`}> <div className={`overlay-wrapper ${this.state.show ? "show" : ""}`}>
<div className="background" /> <div className="background" />
@ -85,13 +107,15 @@ export class _StartupOverlay extends React.PureComponent {
</div> </div>
<div className="firstrun-sign-in"> <div className="firstrun-sign-in">
<p className="form-header"><FormattedMessage id="firstrun_form_header" /><span className="sub-header"><FormattedMessage id="firstrun_form_sub_header" /></span></p> <p className="form-header"><FormattedMessage id="firstrun_form_header" /><span className="sub-header"><FormattedMessage id="firstrun_form_sub_header" /></span></p>
<form method="get" action="https://accounts.firefox.com" target="_blank" rel="noopener noreferrer" onSubmit={this.onSubmit}> <form method="get" action={this.props.fxa_endpoint} target="_blank" rel="noopener noreferrer" onSubmit={this.onSubmit}>
<input name="service" type="hidden" value="sync" /> <input name="service" type="hidden" value="sync" />
<input name="action" type="hidden" value="email" /> <input name="action" type="hidden" value="email" />
<input name="context" type="hidden" value="fx_desktop_v3" /> <input name="context" type="hidden" value="fx_desktop_v3" />
<input name="entrypoint" type="hidden" value="activity-stream-firstrun" /> <input name="entrypoint" type="hidden" value="activity-stream-firstrun" />
<input name="utm_source" type="hidden" value="activity-stream" /> <input name="utm_source" type="hidden" value="activity-stream" />
<input name="utm_campaign" type="hidden" value="firstrun" /> <input name="utm_campaign" type="hidden" value="firstrun" />
<input name="flow_id" type="hidden" value={this.state.flowId} />
<input name="flow_begin_time" type="hidden" value={this.state.flowBeginTime} />
<span className="error">{this.props.intl.formatMessage({id: "firstrun_invalid_input"})}</span> <span className="error">{this.props.intl.formatMessage({id: "firstrun_invalid_input"})}</span>
<input className="email-input" name="email" type="email" required="true" onInvalid={this.onInputInvalid} placeholder={this.props.intl.formatMessage({id: "firstrun_email_input_placeholder"})} onChange={this.onInputChange} /> <input className="email-input" name="email" type="email" required="true" onInvalid={this.onInputInvalid} placeholder={this.props.intl.formatMessage({id: "firstrun_email_input_placeholder"})} onChange={this.onInputChange} />
<div className="extra-links"> <div className="extra-links">
@ -113,4 +137,5 @@ export class _StartupOverlay extends React.PureComponent {
} }
} }
export const StartupOverlay = connect()(injectIntl(_StartupOverlay)); const getState = state => ({fxa_endpoint: state.Prefs.values.fxa_endpoint});
export const StartupOverlay = connect(getState)(injectIntl(_StartupOverlay));

Просмотреть файл

@ -18,7 +18,8 @@ body {
font-size: 16px; font-size: 16px;
overflow-y: scroll; overflow-y: scroll;
&.hide-onboarding, &.hide-main > #onboarding-overlay-button { &.hide-onboarding > #onboarding-overlay-button,
&.hide-main > #onboarding-overlay-button {
display: none !important; display: none !important;
} }

Просмотреть файл

@ -230,7 +230,8 @@ body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Ubuntu', 'Helvetica Neue', sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Ubuntu', 'Helvetica Neue', sans-serif;
font-size: 16px; font-size: 16px;
overflow-y: scroll; } overflow-y: scroll; }
body.hide-onboarding, body.hide-main > #onboarding-overlay-button { body.hide-onboarding > #onboarding-overlay-button,
body.hide-main > #onboarding-overlay-button {
display: none !important; } display: none !important; }
body.hide-main > #onboarding-notification-bar { body.hide-main > #onboarding-notification-bar {
display: none; } display: none; }
@ -1844,6 +1845,9 @@ a.firstrun-link {
height: 30px; height: 30px;
padding: 4px 0 6px; padding: 4px 0 6px;
font-size: 15px; } font-size: 15px; }
.modalOverlayInner .footer .modalButton:focus, .modalOverlayInner .footer .modalButton.active {
box-shadow: 0 0 0 5px var(--newtab-card-active-outline-color);
transition: box-shadow 150ms; }
.SimpleSnippet.tall { .SimpleSnippet.tall {
padding: 27px 0; } padding: 27px 0; }
@ -1976,6 +1980,9 @@ a.firstrun-link {
.onboardingMessage .onboardingButton { .onboardingMessage .onboardingButton {
float: none; float: none;
margin-top: 30px; } } margin-top: 30px; } }
.onboardingMessage .onboardingButton:focus, .onboardingMessage .onboardingButton.active {
box-shadow: 0 0 0 5px var(--newtab-card-active-outline-color);
transition: box-shadow 150ms; }
.onboardingMessage::before { .onboardingMessage::before {
content: ''; content: '';
height: 220px; height: 220px;

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -233,7 +233,8 @@ body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Ubuntu', 'Helvetica Neue', sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Ubuntu', 'Helvetica Neue', sans-serif;
font-size: 16px; font-size: 16px;
overflow-y: scroll; } overflow-y: scroll; }
body.hide-onboarding, body.hide-main > #onboarding-overlay-button { body.hide-onboarding > #onboarding-overlay-button,
body.hide-main > #onboarding-overlay-button {
display: none !important; } display: none !important; }
body.hide-main > #onboarding-notification-bar { body.hide-main > #onboarding-notification-bar {
display: none; } display: none; }
@ -1847,6 +1848,9 @@ a.firstrun-link {
height: 30px; height: 30px;
padding: 4px 0 6px; padding: 4px 0 6px;
font-size: 15px; } font-size: 15px; }
.modalOverlayInner .footer .modalButton:focus, .modalOverlayInner .footer .modalButton.active {
box-shadow: 0 0 0 5px var(--newtab-card-active-outline-color);
transition: box-shadow 150ms; }
.SimpleSnippet.tall { .SimpleSnippet.tall {
padding: 27px 0; } padding: 27px 0; }
@ -1979,6 +1983,9 @@ a.firstrun-link {
.onboardingMessage .onboardingButton { .onboardingMessage .onboardingButton {
float: none; float: none;
margin-top: 30px; } } margin-top: 30px; } }
.onboardingMessage .onboardingButton:focus, .onboardingMessage .onboardingButton.active {
box-shadow: 0 0 0 5px var(--newtab-card-active-outline-color);
transition: box-shadow 150ms; }
.onboardingMessage::before { .onboardingMessage::before {
content: ''; content: '';
height: 220px; height: 220px;

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -230,7 +230,8 @@ body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Ubuntu', 'Helvetica Neue', sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Ubuntu', 'Helvetica Neue', sans-serif;
font-size: 16px; font-size: 16px;
overflow-y: scroll; } overflow-y: scroll; }
body.hide-onboarding, body.hide-main > #onboarding-overlay-button { body.hide-onboarding > #onboarding-overlay-button,
body.hide-main > #onboarding-overlay-button {
display: none !important; } display: none !important; }
body.hide-main > #onboarding-notification-bar { body.hide-main > #onboarding-notification-bar {
display: none; } display: none; }
@ -1844,6 +1845,9 @@ a.firstrun-link {
height: 30px; height: 30px;
padding: 4px 0 6px; padding: 4px 0 6px;
font-size: 15px; } font-size: 15px; }
.modalOverlayInner .footer .modalButton:focus, .modalOverlayInner .footer .modalButton.active {
box-shadow: 0 0 0 5px var(--newtab-card-active-outline-color);
transition: box-shadow 150ms; }
.SimpleSnippet.tall { .SimpleSnippet.tall {
padding: 27px 0; } padding: 27px 0; }
@ -1976,6 +1980,9 @@ a.firstrun-link {
.onboardingMessage .onboardingButton { .onboardingMessage .onboardingButton {
float: none; float: none;
margin-top: 30px; } } margin-top: 30px; } }
.onboardingMessage .onboardingButton:focus, .onboardingMessage .onboardingButton.active {
box-shadow: 0 0 0 5px var(--newtab-card-active-outline-color);
transition: box-shadow 150ms; }
.onboardingMessage::before { .onboardingMessage::before {
content: ''; content: '';
height: 220px; height: 220px;

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -4605,13 +4605,15 @@ const TopSiteList = Object(react_intl__WEBPACK_IMPORTED_MODULE_1__["injectIntl"]
__webpack_require__.r(__webpack_exports__); __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_StartupOverlay", function() { return _StartupOverlay; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_StartupOverlay", function() { return _StartupOverlay; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StartupOverlay", function() { return StartupOverlay; }); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StartupOverlay", function() { return StartupOverlay; });
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); /* harmony import */ var common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
/* harmony import */ var common_Actions_jsm__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2); /* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16);
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_3__);
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
@ -4629,8 +4631,33 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
this.state = { this.state = {
emailInput: "", emailInput: "",
overlayRemoved: false overlayRemoved: false,
flowId: "",
flowBeginTime: 0
}; };
this.didFetch = false;
}
componentWillUpdate() {
var _this = this;
return _asyncToGenerator(function* () {
if (_this.props.fxa_endpoint && !_this.didFetch) {
try {
_this.didFetch = true;
const response = yield fetch(`${_this.props.fxa_endpoint}/metrics-flow`);
if (response.status === 200) {
const { flowId, flowBeginTime } = yield response.json();
_this.setState({ flowId, flowBeginTime });
}
} catch (error) {
_this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].OnlyToMain({ type: common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionTypes"].TELEMETRY_UNDESIRED_EVENT, data: { value: "FXA_METRICS_ERROR" } }));
}
}
})();
}
componentDidMount() {
this.initScene(); this.initScene();
} }
@ -4661,12 +4688,12 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
} }
onSubmit() { onSubmit() {
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_1__["actionCreators"].UserEvent({ event: "SUBMIT_EMAIL" })); this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({ event: "SUBMIT_EMAIL" }));
window.addEventListener("visibilitychange", this.removeOverlay); window.addEventListener("visibilitychange", this.removeOverlay);
} }
clickSkip() { clickSkip() {
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_1__["actionCreators"].UserEvent({ event: "SKIPPED_SIGNIN" })); this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].UserEvent({ event: "SKIPPED_SIGNIN" }));
this.removeOverlay(); this.removeOverlay();
} }
@ -4687,14 +4714,15 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
let termsLink = react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( let termsLink = react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"a", "a",
{ href: "https://accounts.firefox.com/legal/terms", target: "_blank", rel: "noopener noreferrer" }, { href: `${this.props.fxa_endpoint}/legal/terms`, target: "_blank", rel: "noopener noreferrer" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_terms_of_service" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_terms_of_service" })
); );
let privacyLink = react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( let privacyLink = react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"a", "a",
{ href: "https://accounts.firefox.com/legal/privacy", target: "_blank", rel: "noopener noreferrer" }, { href: `${this.props.fxa_endpoint}/legal/privacy`, target: "_blank", rel: "noopener noreferrer" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_privacy_notice" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_privacy_notice" })
); );
return react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( return react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"div", "div",
{ className: `overlay-wrapper ${this.state.show ? "show" : ""}` }, { className: `overlay-wrapper ${this.state.show ? "show" : ""}` },
@ -4711,17 +4739,17 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"h1", "h1",
{ className: "firstrun-title" }, { className: "firstrun-title" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_title" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_title" })
), ),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"p", "p",
{ className: "firstrun-content" }, { className: "firstrun-content" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_content" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_content" })
), ),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"a", "a",
{ className: "firstrun-link", href: "https://www.mozilla.org/firefox/features/sync/", target: "_blank", rel: "noopener noreferrer" }, { className: "firstrun-link", href: "https://www.mozilla.org/firefox/features/sync/", target: "_blank", rel: "noopener noreferrer" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_learn_more_link" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_learn_more_link" })
) )
), ),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
@ -4730,22 +4758,24 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"p", "p",
{ className: "form-header" }, { className: "form-header" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_form_header" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_form_header" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"span", "span",
{ className: "sub-header" }, { className: "sub-header" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_form_sub_header" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_form_sub_header" })
) )
), ),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"form", "form",
{ method: "get", action: "https://accounts.firefox.com", target: "_blank", rel: "noopener noreferrer", onSubmit: this.onSubmit }, { method: "get", action: this.props.fxa_endpoint, target: "_blank", rel: "noopener noreferrer", onSubmit: this.onSubmit },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "service", type: "hidden", value: "sync" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "service", type: "hidden", value: "sync" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "action", type: "hidden", value: "email" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "action", type: "hidden", value: "email" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "context", type: "hidden", value: "fx_desktop_v3" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "context", type: "hidden", value: "fx_desktop_v3" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "entrypoint", type: "hidden", value: "activity-stream-firstrun" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "entrypoint", type: "hidden", value: "activity-stream-firstrun" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "utm_source", type: "hidden", value: "activity-stream" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "utm_source", type: "hidden", value: "activity-stream" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "utm_campaign", type: "hidden", value: "firstrun" }), react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "utm_campaign", type: "hidden", value: "firstrun" }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "flow_id", type: "hidden", value: this.state.flowId }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement("input", { name: "flow_begin_time", type: "hidden", value: this.state.flowBeginTime }),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"span", "span",
{ className: "error" }, { className: "error" },
@ -4755,7 +4785,7 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"div", "div",
{ className: "extra-links" }, { className: "extra-links" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], {
id: "firstrun_extra_legal_links", id: "firstrun_extra_legal_links",
values: { values: {
terms: termsLink, terms: termsLink,
@ -4765,13 +4795,13 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"button", "button",
{ className: "continue-button", type: "submit" }, { className: "continue-button", type: "submit" },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_continue_to_login" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_continue_to_login" })
) )
), ),
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement( react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(
"button", "button",
{ className: "skip-button", disabled: !!this.state.emailInput, onClick: this.clickSkip }, { className: "skip-button", disabled: !!this.state.emailInput, onClick: this.clickSkip },
react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_0__["FormattedMessage"], { id: "firstrun_skip_login" }) react__WEBPACK_IMPORTED_MODULE_3___default.a.createElement(react_intl__WEBPACK_IMPORTED_MODULE_1__["FormattedMessage"], { id: "firstrun_skip_login" })
) )
) )
) )
@ -4780,7 +4810,8 @@ class _StartupOverlay extends react__WEBPACK_IMPORTED_MODULE_3___default.a.PureC
} }
} }
const StartupOverlay = Object(react_redux__WEBPACK_IMPORTED_MODULE_2__["connect"])()(Object(react_intl__WEBPACK_IMPORTED_MODULE_0__["injectIntl"])(_StartupOverlay)); const getState = state => ({ fxa_endpoint: state.Prefs.values.fxa_endpoint });
const StartupOverlay = Object(react_redux__WEBPACK_IMPORTED_MODULE_2__["connect"])(getState)(Object(react_intl__WEBPACK_IMPORTED_MODULE_1__["injectIntl"])(_StartupOverlay));
/***/ }), /***/ }),
/* 37 */ /* 37 */
@ -8100,7 +8131,7 @@ class ModalOverlay_ModalOverlay extends external_React_default.a.PureComponent {
{ className: "footer" }, { className: "footer" },
external_React_default.a.createElement( external_React_default.a.createElement(
"button", "button",
{ onClick: this.props.onDoneButton, className: "button primary modalButton" }, { tabIndex: "2", onClick: this.props.onDoneButton, className: "button primary modalButton" },
" ", " ",
button_label, button_label,
" " " "
@ -8161,7 +8192,7 @@ class OnboardingMessage_OnboardingCard extends external_React_default.a.PureComp
null, null,
external_React_default.a.createElement( external_React_default.a.createElement(
"button", "button",
{ className: "button onboardingButton", onClick: this.onClick }, { tabIndex: "1", className: "button onboardingButton", onClick: this.onClick },
" ", " ",
content.button_label, content.button_label,
" " " "

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -8,7 +8,7 @@
<em:type>2</em:type> <em:type>2</em:type>
<em:bootstrap>true</em:bootstrap> <em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack> <em:unpack>false</em:unpack>
<em:version>2018.07.12.1202-ecc4456e</em:version> <em:version>2018.07.16.1239-6f362fbc</em:version>
<em:name>Activity Stream</em:name> <em:name>Activity Stream</em:name>
<em:description>A rich visual history feed and a reimagined home page make it easier than ever to find exactly what you're looking for in Firefox.</em:description> <em:description>A rich visual history feed and a reimagined home page make it easier than ever to find exactly what you're looking for in Firefox.</em:description>
<em:multiprocessCompatible>true</em:multiprocessCompatible> <em:multiprocessCompatible>true</em:multiprocessCompatible>

Просмотреть файл

@ -16,9 +16,6 @@ const INCOMING_MESSAGE_NAME = "ASRouter:child-to-parent";
const OUTGOING_MESSAGE_NAME = "ASRouter:parent-to-child"; const OUTGOING_MESSAGE_NAME = "ASRouter:parent-to-child";
const ONE_HOUR_IN_MS = 60 * 60 * 1000; const ONE_HOUR_IN_MS = 60 * 60 * 1000;
const SNIPPETS_ENDPOINT_PREF = "browser.newtabpage.activity-stream.asrouter.snippetsUrl"; const SNIPPETS_ENDPOINT_PREF = "browser.newtabpage.activity-stream.asrouter.snippetsUrl";
// Note: currently a restart is required when this pref is changed, this will be fixed in Bug 1462114
const SNIPPETS_ENDPOINT = Services.prefs.getStringPref(SNIPPETS_ENDPOINT_PREF,
"https://activity-stream-icons.services.mozilla.com/v1/messages.json.br");
// List of hosts for endpoints that serve router messages. // List of hosts for endpoints that serve router messages.
// Key is allowed host, value is a name for the endpoint host. // Key is allowed host, value is a name for the endpoint host.
const WHITELIST_HOSTS = { const WHITELIST_HOSTS = {
@ -136,6 +133,35 @@ class _ASRouter {
this.onMessage = this.onMessage.bind(this); this.onMessage = this.onMessage.bind(this);
} }
_addASRouterPrefListener() {
this.state.providers.forEach(provider => {
if (provider.endpointPref) {
Services.prefs.addObserver(provider.endpointPref, this);
}
});
}
// Update provider endpoint and fetch new messages on pref change
async observe(aSubject, aTopic, aPrefName) {
await this.setState(prevState => {
const providers = [...prevState.providers];
this._updateProviderEndpointUrl(providers.find(p => p.endpointPref === aPrefName));
return {providers};
});
await this.loadMessagesFromAllProviders();
}
_updateProviderEndpointUrl(provider) {
if (provider && provider.endpointPref) {
provider.url = Services.prefs.getStringPref(provider.endpointPref, "");
// Reset provider update timestamp to force messages refresh
provider.lastUpdated = undefined;
}
return provider;
}
get state() { get state() {
return this._state; return this._state;
} }
@ -174,7 +200,7 @@ class _ASRouter {
let newState = {messages: [], providers: []}; let newState = {messages: [], providers: []};
for (const provider of this.state.providers) { for (const provider of this.state.providers) {
if (needsUpdate.includes(provider)) { if (needsUpdate.includes(provider)) {
const {messages, lastUpdated} = await MessageLoaderUtils.loadMessagesForProvider(provider); const {messages, lastUpdated} = await MessageLoaderUtils.loadMessagesForProvider(this._updateProviderEndpointUrl(provider));
newState.providers.push({...provider, lastUpdated}); newState.providers.push({...provider, lastUpdated});
newState.messages = [...newState.messages, ...messages]; newState.messages = [...newState.messages, ...messages];
} else { } else {
@ -199,6 +225,7 @@ class _ASRouter {
async init(channel, storage) { async init(channel, storage) {
this.messageChannel = channel; this.messageChannel = channel;
this.messageChannel.addMessageListener(INCOMING_MESSAGE_NAME, this.onMessage); this.messageChannel.addMessageListener(INCOMING_MESSAGE_NAME, this.onMessage);
this._addASRouterPrefListener();
await this.loadMessagesFromAllProviders(); await this.loadMessagesFromAllProviders();
this._storage = storage; this._storage = storage;
@ -212,6 +239,11 @@ class _ASRouter {
this.messageChannel.sendAsyncMessage(OUTGOING_MESSAGE_NAME, {type: "CLEAR_ALL"}); this.messageChannel.sendAsyncMessage(OUTGOING_MESSAGE_NAME, {type: "CLEAR_ALL"});
this.messageChannel.removeMessageListener(INCOMING_MESSAGE_NAME, this.onMessage); this.messageChannel.removeMessageListener(INCOMING_MESSAGE_NAME, this.onMessage);
this.messageChannel = null; this.messageChannel = null;
this.state.providers.forEach(provider => {
if (provider.endpointPref) {
Services.prefs.removeObserver(provider.endpointPref, this);
}
});
this._resetInitialization(); this._resetInitialization();
} }
@ -453,7 +485,7 @@ this._ASRouter = _ASRouter;
this.ASRouter = new _ASRouter({ this.ASRouter = new _ASRouter({
providers: [ providers: [
{id: "onboarding", type: "local", messages: OnboardingMessageProvider.getMessages()}, {id: "onboarding", type: "local", messages: OnboardingMessageProvider.getMessages()},
{id: "snippets", type: "remote", url: SNIPPETS_ENDPOINT, updateCycleInMs: ONE_HOUR_IN_MS * 4} {id: "snippets", type: "remote", endpointPref: SNIPPETS_ENDPOINT_PREF, updateCycleInMs: ONE_HOUR_IN_MS * 4}
] ]
}); });

Просмотреть файл

@ -168,7 +168,7 @@ const PREFS_CONFIG = new Map([
}], }],
["asrouter.snippetsUrl", { ["asrouter.snippetsUrl", {
title: "A custom URL for the AS router snippets", title: "A custom URL for the AS router snippets",
value: "" value: "https://activity-stream-icons.services.mozilla.com/v1/messages.json.br"
}] }]
]); ]);

Просмотреть файл

@ -101,6 +101,10 @@ this.PrefsFeed = class PrefsFeed {
values.isPrivateBrowsingEnabled = PrivateBrowsingUtils.enabled; values.isPrivateBrowsingEnabled = PrivateBrowsingUtils.enabled;
values.platform = AppConstants.platform; values.platform = AppConstants.platform;
// Get the firefox accounts url for links and to send firstrun metrics to.
values.fxa_endpoint = Services.prefs.getStringPref(
"browser.newtabpage.activity-stream.fxaccounts.endpoint", "https://accounts.firefox.com");
// Set the initial state of all prefs in redux // Set the initial state of all prefs in redux
this.store.dispatch(ac.BroadcastToContent({type: at.PREFS_INITIAL_VALUES, data: values})); this.store.dispatch(ac.BroadcastToContent({type: at.PREFS_INITIAL_VALUES, data: values}));

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=richin yatok pa Firefox Sync.
firstrun_email_input_placeholder=Taqoya'l firstrun_email_input_placeholder=Taqoya'l
firstrun_invalid_input=Najowäx ütz chi taqoya'l
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and # LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links. # {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Toq nasamajij qa, nawojqaj ri {terms} chuqa' {privacy}. firstrun_extra_legal_links=Toq nasamajij qa, nawojqaj ri {terms} chuqa' {privacy}.

Просмотреть файл

@ -73,7 +73,7 @@ search_header=Αναζήτηση {search_engine_name}
# LOCALIZATION NOTE (search_web_placeholder): This is shown in the searchbox when # LOCALIZATION NOTE (search_web_placeholder): This is shown in the searchbox when
# the user hasn't typed anything yet. # the user hasn't typed anything yet.
search_web_placeholder=Αναζήτηση στον ιστό search_web_placeholder=Αναζήτηση στο διαδίκτυο
# LOCALIZATION NOTE (section_disclaimer_topstories): This is shown below # LOCALIZATION NOTE (section_disclaimer_topstories): This is shown below
# the topstories section title to provide additional information about # the topstories section title to provide additional information about
@ -95,7 +95,7 @@ prefs_home_description=Επιλέξτε τι περιεχόμενο θέλετε
# plural forms used in a drop down of multiple row options (1 row, 2 rows). # plural forms used in a drop down of multiple row options (1 row, 2 rows).
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
prefs_section_rows_option={num} σειρά;{num} σειρές prefs_section_rows_option={num} σειρά;{num} σειρές
prefs_search_header=Αναζήτηση ιστού prefs_search_header=Διαδικτυακή αναζήτηση
prefs_topsites_description=Οι ιστοσελίδες που επισκέπτεστε περισσότερο prefs_topsites_description=Οι ιστοσελίδες που επισκέπτεστε περισσότερο
prefs_topstories_description2=Εξαιρετικό περιεχόμενο από το διαδίκτυο, εξατομικευμένο για εσάς prefs_topstories_description2=Εξαιρετικό περιεχόμενο από το διαδίκτυο, εξατομικευμένο για εσάς
prefs_topstories_options_sponsored_label=Χορηγούμενες ιστορίες prefs_topstories_options_sponsored_label=Χορηγούμενες ιστορίες

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=por pluiri al Spegulado de Firefox.
firstrun_email_input_placeholder=Retpoŝta adreso firstrun_email_input_placeholder=Retpoŝta adreso
firstrun_invalid_input=Valida retpoŝta adreso postulata
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and # LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links. # {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Se vi daŭrigas vi akceptas la {terms} kaj {privacy}. firstrun_extra_legal_links=Se vi daŭrigas vi akceptas la {terms} kaj {privacy}.

Просмотреть файл

@ -49,6 +49,7 @@ menu_action_archive_pocket=पॉकेट में पुरालेख
# found in the context menu of an item that has been downloaded. The intention behind # found in the context menu of an item that has been downloaded. The intention behind
# "this action" is that it will show where the downloaded file exists on the file system # "this action" is that it will show where the downloaded file exists on the file system
# for each operating system. # for each operating system.
menu_action_show_file_mac_os=फाइंडर में दिखाएँ
menu_action_show_file_windows=संग्राहक फोल्डर खोलें menu_action_show_file_windows=संग्राहक फोल्डर खोलें
menu_action_show_file_linux=संग्राहक फोल्डर खोलें menu_action_show_file_linux=संग्राहक फोल्डर खोलें
menu_action_show_file_default=फ़ाइल दिखाएं menu_action_show_file_default=फ़ाइल दिखाएं
@ -101,6 +102,7 @@ prefs_topstories_options_sponsored_label=प्रायोजित कहा
prefs_topstories_sponsored_learn_more=अधिक जानें prefs_topstories_sponsored_learn_more=अधिक जानें
prefs_highlights_description=आपके द्वारा सहेजी गई या विज़िट की गई साइटों का चयन prefs_highlights_description=आपके द्वारा सहेजी गई या विज़िट की गई साइटों का चयन
prefs_highlights_options_visited_label=देखे गए पृष्ठ prefs_highlights_options_visited_label=देखे गए पृष्ठ
prefs_highlights_options_download_label=सबसे हालिया डाउनलोड
prefs_highlights_options_pocket_label=पॉकेट में सहेजे गए पृष्ठ prefs_highlights_options_pocket_label=पॉकेट में सहेजे गए पृष्ठ
prefs_snippets_description=Mozilla और Firefox से अद्यतन prefs_snippets_description=Mozilla और Firefox से अद्यतन
settings_pane_button_label=अपने नए टैब पृष्ठ को अनुकूलित करें settings_pane_button_label=अपने नए टैब पृष्ठ को अनुकूलित करें

Просмотреть файл

@ -1,113 +0,0 @@
# LOCALIZATION NOTE(header_recommended_by): This is followed by the name
# of the corresponding content provider.
# LOCALIZATION NOTE(context_menu_button_sr): This is for screen readers when
# the context menu button is focused/active. Title is the label or hostname of
# the site.
# LOCALIZATION NOTE(section_context_menu_button_sr): This is for screen readers when
# the section edit context menu button is focused/active.
# LOCALIZATION NOTE (type_label_*): These labels are associated to pages to give
# context on how the element is related to the user, e.g. type indicates that
# the page is bookmarked, or is currently open on another device
# LOCALIZATION NOTE (menu_action_*): These strings are displayed in a context
# menu and are meant as a call to action for a given page.
# LOCALIZATION NOTE (menu_action_bookmark): Bookmark is a verb, as in "Add to
# bookmarks"
menu_action_pin=Chita'an
# LOCALIZATION NOTE (confirm_history_delete_notice_p2): this string is displayed in
# the same dialog as confirm_history_delete_p1. "This action" refers to deleting a
# page from history.
# LOCALIZATION NOTE (menu_action_show_file_*): These are platform specific strings
# found in the context menu of an item that has been downloaded. The intention behind
# "this action" is that it will show where the downloaded file exists on the file system
# for each operating system.
menu_action_open_file=Kuna tutu
# LOCALIZATION NOTE (menu_action_copy_download_link, menu_action_go_to_download_page):
# "Download" here, in both cases, is not a verb, it is a noun. As in, "Copy the
# link that belongs to this downloaded item"
# LOCALIZATION NOTE (search_button): This is screenreader only text for the
# search button.
search_button=Nduku
# LOCALIZATION NOTE (search_header): Displayed at the top of the panel
# showing search suggestions. {search_engine_name} is replaced with the name of
# the current default search engine. e.g. 'Google Search'
search_header={search_engine_name} Nduku
# LOCALIZATION NOTE (search_web_placeholder): This is shown in the searchbox when
# the user hasn't typed anything yet.
search_web_placeholder=Nduku nu Web
# LOCALIZATION NOTE (section_disclaimer_topstories): This is shown below
# the topstories section title to provide additional information about
# how the stories are selected.
# LOCALIZATION NOTE (section_disclaimer_topstories_buttontext): The text of
# the button used to acknowledge, and hide this disclaimer in the future.
# LOCALIZATION NOTE (prefs_*, settings_*): These are shown in about:preferences
# for a "Firefox Home" section. "Firefox" should be treated as a brand and kept
# in English, while "Home" should be localized matching the about:preferences
# sidebar mozilla-central string for the panel that has preferences related to
# what is shown for the homepage, new windows, and new tabs.
# LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
# plural forms used in a drop down of multiple row options (1 row, 2 rows).
# See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
prefs_topstories_sponsored_learn_more=Skua'a kuakaa
# LOCALIZATION NOTE(settings_pane_snippets_header): For the "Snippets" feature
# traditionally on about:home. Alternative translation options: "Small Note" or
# something that expresses the idea of "a small message, shortened from
# something else, and non-essential but also not entirely trivial and useless."
# LOCALIZATION NOTE (edit_topsites_*): This is shown in the Edit Top Sites modal
# dialog.
edit_topsites_button_text=Sama
# LOCALIZATION NOTE (topsites_form_*): This is shown in the New/Edit Topsite modal.
topsites_form_url_label=URL
# LOCALIZATION NOTE (topsites_form_*_button): These are verbs/actions.
topsites_form_add_button=Chikaa
topsites_form_save_button=Chika vaà
topsites_form_cancel_button=Kunchatu
# LOCALIZATION NOTE (pocket_read_more): This is shown at the bottom of the
# trending stories section and precedes a list of links to popular topics.
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
# end of the list of popular topic links.
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
# in the space that would have shown a few stories, this is shown instead.
# {provider} is replaced by the name of the content provider for this section.
# LOCALIZATION NOTE (manual_migration_explanation2): This message is shown to encourage users to
# import their browser profile from another browser they might be using.
# LOCALIZATION NOTE (manual_migration_cancel_button): This message is shown on a button that cancels the
# process of importing another browsers profile into Firefox.
# LOCALIZATION NOTE (manual_migration_import_button): This message is shown on a button that starts the process
# of importing another browsers profile profile into Firefox.
# LOCALIZATION NOTE (error_fallback_default_*): This message and suggested
# action link are shown in each section of UI that fails to render
# LOCALIZATION NOTE (section_menu_action_*). These strings are displayed in the section
# context menu and are meant as a call to action for the given section.
section_menu_action_move_up=Kanta kuchi
section_menu_action_move_down=Kanta ninu
# LOCALIZATION NOTE (firstrun_*). These strings are displayed only once, on the
# firstrun of the browser, they give an introduction to Firefox and Sync.
# LOCALIZATION NOTE (firstrun_form_header and firstrun_form_sub_header):
# firstrun_form_sub_header is a continuation of firstrun_form_header, they are one sentence.
# firstrun_form_header is displayed more boldly as the call to action.
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.

Просмотреть файл

@ -190,6 +190,8 @@ firstrun_form_sub_header=per contunhar amb Firefox Sync.
firstrun_email_input_placeholder=Adreça electronica firstrun_email_input_placeholder=Adreça electronica
firstrun_invalid_input=Cal una adreça electronica valida
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and # LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links. # {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Se contunhatz, acceptatz las {terms} e l{privacy}. firstrun_extra_legal_links=Se contunhatz, acceptatz las {terms} e l{privacy}.

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=чтобы продолжить использоват
firstrun_email_input_placeholder=Эл. почта firstrun_email_input_placeholder=Эл. почта
firstrun_invalid_input=Введите действующий адрес электронной почты
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and # LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links. # {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Продолжая, вы соглашаетесь с {terms} и {privacy}. firstrun_extra_legal_links=Продолжая, вы соглашаетесь с {terms} и {privacy}.

Просмотреть файл

@ -1,32 +1,24 @@
newtab_page_title=නව ටැබය newtab_page_title=නව ටැබය
default_label_loading=පූරණය වෙමින්…
header_top_sites=ප්‍රමුඛ අඩවි header_top_sites=ප්‍රමුඛ අඩවි
header_stories=ප්‍රමුඛ පුවත්
header_highlights=ඉස්මතු කිරීම් header_highlights=ඉස්මතු කිරීම්
header_visit_again=යළි පිවිසෙන්න
header_bookmarks=නැවුම් පිටු සලකුණු
# LOCALIZATION NOTE(header_recommended_by): This is followed by the name # LOCALIZATION NOTE(header_recommended_by): This is followed by the name
# of the corresponding content provider. # of the corresponding content provider.
header_recommended_by={provider} විසින් නිර්දේශිතයි header_recommended_by={provider} විසින් නිර්දේශිතයි
# LOCALIZATION NOTE(header_bookmarks_placeholder): This message is
# meant to inform that section contains no information because # LOCALIZATION NOTE(context_menu_button_sr): This is for screen readers when
# the user hasn't added any bookmarks. # the context menu button is focused/active. Title is the label or hostname of
header_bookmarks_placeholder=ඔබ සතුව තවම පිටුසලකුණු නැත. # the site.
# LOCALIZATION NOTE(header_stories_from): This is followed by a logo of the
# corresponding content (stories) provider # LOCALIZATION NOTE(section_context_menu_button_sr): This is for screen readers when
header_stories_from=සිට​ # the section edit context menu button is focused/active.
# LOCALIZATION NOTE (type_label_*): These labels are associated to pages to give # LOCALIZATION NOTE (type_label_*): These labels are associated to pages to give
# context on how the element is related to the user, e.g. type indicates that # context on how the element is related to the user, e.g. type indicates that
# the page is bookmarked, or is currently open on another device # the page is bookmarked, or is currently open on another device
type_label_visited=ප්‍රවේශිත type_label_visited=ප්‍රවේශිත
type_label_bookmarked=පිටු සලකුණු තැබූ type_label_bookmarked=පිටු සලකුණු තැබූ
type_label_synced=වෙනත් උපාංගයක් වෙතින් සමකාලීන​ කර ඇත​ type_label_pocket=Pocket හි සුරකින ලදී
# LOCALIZATION NOTE(type_label_open): Open is an adjective, as in "page is open"
type_label_open=විවෘත
type_label_topic=මාතෘකාව
type_label_now=දැන්
# LOCALIZATION NOTE (menu_action_*): These strings are displayed in a context # LOCALIZATION NOTE (menu_action_*): These strings are displayed in a context
# menu and are meant as a call to action for a given page. # menu and are meant as a call to action for a given page.
@ -34,8 +26,6 @@ type_label_now=දැන්
# bookmarks" # bookmarks"
menu_action_bookmark=පිටු සලකුණ menu_action_bookmark=පිටු සලකුණ
menu_action_remove_bookmark=පිටු සලකුණ ඉවත් කරන්න menu_action_remove_bookmark=පිටු සලකුණ ඉවත් කරන්න
menu_action_copy_address=ලිපිනය පිටපත් කරන්න
menu_action_email_link=විද්‍යුත් තැපැල් සබැඳි…
menu_action_open_new_window=නව කවුළුවක විවෘත කරන්න menu_action_open_new_window=නව කවුළුවක විවෘත කරන්න
menu_action_open_private_window=නව පුද්ගලික කවුළුවක විවෘත කරන්න menu_action_open_private_window=නව පුද්ගලික කවුළුවක විවෘත කරන්න
menu_action_dismiss=ඉවත් කරන්න menu_action_dismiss=ඉවත් කරන්න
@ -47,12 +37,18 @@ confirm_history_delete_p1=ඔබට මෙම පිටුවට අදාල
# the same dialog as confirm_history_delete_p1. "This action" refers to deleting a # the same dialog as confirm_history_delete_p1. "This action" refers to deleting a
# page from history. # page from history.
confirm_history_delete_notice_p2=මෙම ක්‍රියාව අහෝසි කළ නොහැක. confirm_history_delete_notice_p2=මෙම ක්‍රියාව අහෝසි කළ නොහැක.
menu_action_save_to_pocket=Pocket හි සුරකින්න
menu_action_delete_pocket=Pocket වෙතින් මකන්න
menu_action_archive_pocket=Pocket හි සංරක්ෂණ කරන්න
# LOCALIZATION NOTE (search_for_something_with): {search_term} is a placeholder # LOCALIZATION NOTE (menu_action_show_file_*): These are platform specific strings
# for what the user has typed in the search input field, e.g. 'Search for ' + # found in the context menu of an item that has been downloaded. The intention behind
# search_term + 'with:' becomes 'Search for abc with:' # "this action" is that it will show where the downloaded file exists on the file system
# The search engine name is displayed as an icon and does not need a translation # for each operating system.
search_for_something_with={search_term} සදහා සෙවීමට භාවිත කළ යුත්තේ:
# LOCALIZATION NOTE (menu_action_copy_download_link, menu_action_go_to_download_page):
# "Download" here, in both cases, is not a verb, it is a noun. As in, "Copy the
# link that belongs to this downloaded item"
# LOCALIZATION NOTE (search_button): This is screenreader only text for the # LOCALIZATION NOTE (search_button): This is screenreader only text for the
# search button. # search button.
@ -66,13 +62,6 @@ search_header={search_engine_name} ෙසවුම
# LOCALIZATION NOTE (search_web_placeholder): This is shown in the searchbox when # LOCALIZATION NOTE (search_web_placeholder): This is shown in the searchbox when
# the user hasn't typed anything yet. # the user hasn't typed anything yet.
search_web_placeholder=ජාලය තුළ සොයන්න search_web_placeholder=ජාලය තුළ සොයන්න
search_settings=සෙවුම් සැකසුම් වෙනස් කරන්න
# LOCALIZATION NOTE (section_info_option): This is the screenreader text for the
# (?) icon that would show a section's description with optional feedback link.
section_info_option=තොරතුරු
section_info_send_feedback=ප්‍රතිචාරය යවන්න
section_info_privacy_notice=පෞද්ගලිකත්ව දැනුම්දීම්
# LOCALIZATION NOTE (section_disclaimer_topstories): This is shown below # LOCALIZATION NOTE (section_disclaimer_topstories): This is shown below
# the topstories section title to provide additional information about # the topstories section title to provide additional information about
@ -82,55 +71,42 @@ section_disclaimer_topstories_linktext=එය ක්‍රියාකරන්
# the button used to acknowledge, and hide this disclaimer in the future. # the button used to acknowledge, and hide this disclaimer in the future.
section_disclaimer_topstories_buttontext=හරි, තේරුණා section_disclaimer_topstories_buttontext=හරි, තේරුණා
# LOCALIZATION NOTE (welcome_*): This is shown as a modal dialog, typically on a # LOCALIZATION NOTE (prefs_*, settings_*): These are shown in about:preferences
# first-run experience when there's no data to display yet # for a "Firefox Home" section. "Firefox" should be treated as a brand and kept
welcome_title=නව ටැබයට සාදරයෙන් පිළිගනිමු # in English, while "Home" should be localized matching the about:preferences
welcome_body=ඔබට පහසුවෙන් යළි භාවිතයට පහසු කරවීමට, Firefox මෙම ඉඩ ඔබට වඩාත් අදාල පිටු සළකුණු, ලිපි, විඩියෝ සහ ඔබ මෑතකදී පිවිසි පිටු පෙන්වීම සදහා භාවිත කරයි. # sidebar mozilla-central string for the panel that has preferences related to
welcome_label=ඔබේ ඉස්මතු කිරීම් හදුනාගනිමින් # what is shown for the homepage, new windows, and new tabs.
prefs_home_header=Firefox මුල්පිටු අන්තර්ගතය
# LOCALIZATION NOTE (time_label_*): {number} is a placeholder for a number which prefs_home_description=Firefox මුල් පිටුවෙහි ඔබට අවැසි වන්නේ කුමන අන්තර්ගතයදැයි තෝරන්න.
# represents a shortened timestamp format, e.g. '10m' means '10 minutes ago'. # LOCALIZATION NOTE (prefs_section_rows_option): This is a semi-colon list of
time_label_less_than_minute=<1m # plural forms used in a drop down of multiple row options (1 row, 2 rows).
time_label_minute={number} මිනිත්තු # See: http://developer.mozilla.org/en/docs/Localization_and_Plurals
time_label_hour={number}පැය prefs_section_rows_option={num} තීරය;{num} තීර
time_label_day={number}දින prefs_search_header=ජාල සෙවුම
prefs_topsites_description=ඔබ වැඩිපුරම පිවිසෙන අඩවි
# LOCALIZATION NOTE (settings_pane_*): This is shown in the Settings Pane sidebar. prefs_topstories_sponsored_learn_more=තවත් දැනගන්න
settings_pane_button_label=ඔබේ නව ටැබ පිටුව රුචිකරණය කරන්න settings_pane_button_label=ඔබේ නව ටැබ පිටුව රුචිකරණය කරන්න
settings_pane_header=නව ටැබ අභිප්‍රේත
settings_pane_body2=මෙම පිටුවේ ඔබ දැකිය යුතු දේ තෝරන්න.
settings_pane_search_header=සොයන්න
settings_pane_search_body=ඔබේ නව ටැබයෙන් වෙබ් සෙවීම.
settings_pane_topsites_header=ප්‍රමුඛ අඩවි settings_pane_topsites_header=ප්‍රමුඛ අඩවි
settings_pane_topsites_body=ඔබ නිරතුරුව පිවිසෙන වෙබ් අඩවි වෙත ප්‍රවේශය.
settings_pane_topsites_options_showmore=පේළි දෙකක් පෙන්වන්න
settings_pane_bookmarks_header=නැවුම් පිටු සලකුණු
settings_pane_bookmarks_body=ඔබේ නැවුම් පිටු සලකුණු එක් ස්ථානයක.
settings_pane_visit_again_header=යළි පිවිසෙන්න
settings_pane_highlights_header=ඉස්මතු කිරීම් settings_pane_highlights_header=ඉස්මතු කිරීම්
settings_pane_highlights_options_bookmarks=පිටු සලකුණු settings_pane_highlights_options_bookmarks=පිටු සලකුණු
settings_pane_highlights_options_visited=පිවිසුණු අඩවි
# LOCALIZATION NOTE(settings_pane_snippets_header): For the "Snippets" feature # LOCALIZATION NOTE(settings_pane_snippets_header): For the "Snippets" feature
# traditionally on about:home. Alternative translation options: "Small Note" or # traditionally on about:home. Alternative translation options: "Small Note" or
# something that expresses the idea of "a small message, shortened from # something that expresses the idea of "a small message, shortened from
# something else, and non-essential but also not entirely trivial and useless." # something else, and non-essential but also not entirely trivial and useless."
settings_pane_topstories_options_sponsored=අනුග්‍රහක පුවත් පෙන්වන්න
# LOCALIZATION NOTE (edit_topsites_*): This is shown in the Edit Top Sites modal # LOCALIZATION NOTE (edit_topsites_*): This is shown in the Edit Top Sites modal
# dialog. # dialog.
edit_topsites_button_text=සැකසුම් edit_topsites_button_text=සැකසුම්
edit_topsites_showmore_button=තවත් පෙන්වන්න
edit_topsites_showless_button=අඩුවෙන් පෙන්වන්න
edit_topsites_done_button=කළා
edit_topsites_edit_button=මෙම අඩවිය සකසන්න edit_topsites_edit_button=මෙම අඩවිය සකසන්න
edit_topsites_dismiss_button=මෙම අඩවිය ඉවත ලන්න
edit_topsites_add_button=එක් කරන්න
# LOCALIZATION NOTE (topsites_form_*): This is shown in the New/Edit Topsite modal. # LOCALIZATION NOTE (topsites_form_*): This is shown in the New/Edit Topsite modal.
topsites_form_add_header=නව ප්‍රමුඛ අඩවියක් topsites_form_add_header=නව ප්‍රමුඛ අඩවියක්
topsites_form_edit_header=ප්‍රමුඛ අඩවිය සකසන්න topsites_form_edit_header=ප්‍රමුඛ අඩවිය සකසන්න
topsites_form_title_label=මාතෘකාව
topsites_form_title_placeholder=සිරස්තල එක් කරන්න topsites_form_title_placeholder=සිරස්තල එක් කරන්න
topsites_form_url_label=URL
topsites_form_url_placeholder=URL එකක් ඇතුළත් කරන්න topsites_form_url_placeholder=URL එකක් ඇතුළත් කරන්න
# LOCALIZATION NOTE (topsites_form_*_button): These are verbs/actions.
topsites_form_add_button=එක් කරන්න topsites_form_add_button=එක් කරන්න
topsites_form_save_button=සුරකින්න topsites_form_save_button=සුරකින්න
topsites_form_cancel_button=අවලංගු කරන්න topsites_form_cancel_button=අවලංගු කරන්න
@ -142,10 +118,6 @@ pocket_read_more=ජනප්‍රිය මාතෘකා:
# LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the # LOCALIZATION NOTE (pocket_read_even_more): This is shown as a link at the
# end of the list of popular topic links. # end of the list of popular topic links.
pocket_read_even_more=තවත් බොහෝ දැ pocket_read_even_more=තවත් බොහෝ දැ
# LOCALIZATION NOTE (pocket_feedback_header): This is shown as an introduction
# to Pocket as part of the feedback form.
# LOCALIZATION NOTE (pocket_description): This is shown in the settings pane and
# below (pocket_feedback_header) to provide more information about Pocket.
# LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations, # LOCALIZATION NOTE (topstories_empty_state): When there are no recommendations,
# in the space that would have shown a few stories, this is shown instead. # in the space that would have shown a few stories, this is shown instead.
@ -160,3 +132,25 @@ manual_migration_cancel_button=එපා, ස්තුතියි
# LOCALIZATION NOTE (manual_migration_import_button): This message is shown on a button that starts the process # LOCALIZATION NOTE (manual_migration_import_button): This message is shown on a button that starts the process
# of importing another browsers profile profile into Firefox. # of importing another browsers profile profile into Firefox.
manual_migration_import_button=දැන් ආයාත කරන්න manual_migration_import_button=දැන් ආයාත කරන්න
# LOCALIZATION NOTE (error_fallback_default_*): This message and suggested
# action link are shown in each section of UI that fails to render
# LOCALIZATION NOTE (section_menu_action_*). These strings are displayed in the section
# context menu and are meant as a call to action for the given section.
section_menu_action_move_up=ඉහළට ගෙනයන්න
section_menu_action_move_down=පහළට ගෙනයන්න
section_menu_action_privacy_notice=පෞද්ගලිකත්ව සටහන
# LOCALIZATION NOTE (firstrun_*). These strings are displayed only once, on the
# firstrun of the browser, they give an introduction to Firefox and Sync.
# LOCALIZATION NOTE (firstrun_form_header and firstrun_form_sub_header):
# firstrun_form_sub_header is a continuation of firstrun_form_header, they are one sentence.
# firstrun_form_header is displayed more boldly as the call to action.
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.

Просмотреть файл

@ -191,6 +191,8 @@ firstrun_form_sub_header=a používajte službu Firefox Sync.
firstrun_email_input_placeholder=E-mail firstrun_email_input_placeholder=E-mail
firstrun_invalid_input=Vyžaduje sa platná e-mailová adresa
# LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and # LOCALIZATION NOTE (firstrun_extra_legal_links): {terms} is equal to firstrun_terms_of_service, and
# {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links. # {privacy} is equal to firstrun_privacy_notice. {terms} and {privacy} are clickable links.
firstrun_extra_legal_links=Pokračovaním súhlasíte s {terms} a {privacy}. firstrun_extra_legal_links=Pokračovaním súhlasíte s {terms} a {privacy}.

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Tatz'ib'aj ri ataqoya'l", "firstrun_form_header": "Tatz'ib'aj ri ataqoya'l",
"firstrun_form_sub_header": "richin yatok pa Firefox Sync.", "firstrun_form_sub_header": "richin yatok pa Firefox Sync.",
"firstrun_email_input_placeholder": "Taqoya'l", "firstrun_email_input_placeholder": "Taqoya'l",
"firstrun_invalid_input": "Valid email required", "firstrun_invalid_input": "Najowäx ütz chi taqoya'l",
"firstrun_extra_legal_links": "Toq nasamajij qa, nawojqaj ri {terms} chuqa' {privacy}.", "firstrun_extra_legal_links": "Toq nasamajij qa, nawojqaj ri {terms} chuqa' {privacy}.",
"firstrun_terms_of_service": "Kojqanem Samaj", "firstrun_terms_of_service": "Kojqanem Samaj",
"firstrun_privacy_notice": "Ichinan Na'oj", "firstrun_privacy_notice": "Ichinan Na'oj",

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -34,14 +34,14 @@ window.gActivityStreamStrings = {
"menu_action_remove_download": "Αφαίρεση από το ιστορικό", "menu_action_remove_download": "Αφαίρεση από το ιστορικό",
"search_button": "Αναζήτηση", "search_button": "Αναζήτηση",
"search_header": "Αναζήτηση {search_engine_name}", "search_header": "Αναζήτηση {search_engine_name}",
"search_web_placeholder": "Αναζήτηση στον ιστό", "search_web_placeholder": "Αναζήτηση στο διαδίκτυο",
"section_disclaimer_topstories": "Οι πιο ενδιαφέρουσες ιστορίες στο διαδίκτυο, επιλεγμένες βάσει όσων διαβάζετε. Από το Pocket, πλέον μέλος της Mozilla.", "section_disclaimer_topstories": "Οι πιο ενδιαφέρουσες ιστορίες στο διαδίκτυο, επιλεγμένες βάσει όσων διαβάζετε. Από το Pocket, πλέον μέλος της Mozilla.",
"section_disclaimer_topstories_linktext": "Μάθετε πώς λειτουργεί.", "section_disclaimer_topstories_linktext": "Μάθετε πώς λειτουργεί.",
"section_disclaimer_topstories_buttontext": "Εντάξει, το 'πιασα", "section_disclaimer_topstories_buttontext": "Εντάξει, το 'πιασα",
"prefs_home_header": "Περιεχόμενο αρχικής σελίδας Firefox", "prefs_home_header": "Περιεχόμενο αρχικής σελίδας Firefox",
"prefs_home_description": "Επιλέξτε τι περιεχόμενο θέλετε στην αρχική σελίδα του Firefox σας.", "prefs_home_description": "Επιλέξτε τι περιεχόμενο θέλετε στην αρχική σελίδα του Firefox σας.",
"prefs_section_rows_option": "{num} σειρά;{num} σειρές", "prefs_section_rows_option": "{num} σειρά;{num} σειρές",
"prefs_search_header": "Αναζήτηση ιστού", "prefs_search_header": "Διαδικτυακή αναζήτηση",
"prefs_topsites_description": "Οι ιστοσελίδες που επισκέπτεστε περισσότερο", "prefs_topsites_description": "Οι ιστοσελίδες που επισκέπτεστε περισσότερο",
"prefs_topstories_description2": "Εξαιρετικό περιεχόμενο από το διαδίκτυο, εξατομικευμένο για εσάς", "prefs_topstories_description2": "Εξαιρετικό περιεχόμενο από το διαδίκτυο, εξατομικευμένο για εσάς",
"prefs_topstories_options_sponsored_label": "Χορηγούμενες ιστορίες", "prefs_topstories_options_sponsored_label": "Χορηγούμενες ιστορίες",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Tajpu vian retpoŝtan adreson", "firstrun_form_header": "Tajpu vian retpoŝtan adreson",
"firstrun_form_sub_header": "por pluiri al Spegulado de Firefox.", "firstrun_form_sub_header": "por pluiri al Spegulado de Firefox.",
"firstrun_email_input_placeholder": "Retpoŝta adreso", "firstrun_email_input_placeholder": "Retpoŝta adreso",
"firstrun_invalid_input": "Valid email required", "firstrun_invalid_input": "Valida retpoŝta adreso postulata",
"firstrun_extra_legal_links": "Se vi daŭrigas vi akceptas la {terms} kaj {privacy}.", "firstrun_extra_legal_links": "Se vi daŭrigas vi akceptas la {terms} kaj {privacy}.",
"firstrun_terms_of_service": "kondiĉojn de uzo", "firstrun_terms_of_service": "kondiĉojn de uzo",
"firstrun_privacy_notice": "rimarkon pri privateco", "firstrun_privacy_notice": "rimarkon pri privateco",

Просмотреть файл

@ -24,7 +24,7 @@ window.gActivityStreamStrings = {
"menu_action_save_to_pocket": "Pocket में सहेजें", "menu_action_save_to_pocket": "Pocket में सहेजें",
"menu_action_delete_pocket": "पॉकेट से हटाएं", "menu_action_delete_pocket": "पॉकेट से हटाएं",
"menu_action_archive_pocket": "पॉकेट में पुरालेख", "menu_action_archive_pocket": "पॉकेट में पुरालेख",
"menu_action_show_file_mac_os": "Show in Finder", "menu_action_show_file_mac_os": "फाइंडर में दिखाएँ",
"menu_action_show_file_windows": "संग्राहक फोल्डर खोलें", "menu_action_show_file_windows": "संग्राहक फोल्डर खोलें",
"menu_action_show_file_linux": "संग्राहक फोल्डर खोलें", "menu_action_show_file_linux": "संग्राहक फोल्डर खोलें",
"menu_action_show_file_default": "फ़ाइल दिखाएं", "menu_action_show_file_default": "फ़ाइल दिखाएं",
@ -48,7 +48,7 @@ window.gActivityStreamStrings = {
"prefs_topstories_sponsored_learn_more": "अधिक जानें", "prefs_topstories_sponsored_learn_more": "अधिक जानें",
"prefs_highlights_description": "आपके द्वारा सहेजी गई या विज़िट की गई साइटों का चयन", "prefs_highlights_description": "आपके द्वारा सहेजी गई या विज़िट की गई साइटों का चयन",
"prefs_highlights_options_visited_label": "देखे गए पृष्ठ", "prefs_highlights_options_visited_label": "देखे गए पृष्ठ",
"prefs_highlights_options_download_label": "Most Recent Download", "prefs_highlights_options_download_label": "सबसे हालिया डाउनलोड",
"prefs_highlights_options_pocket_label": "पॉकेट में सहेजे गए पृष्ठ", "prefs_highlights_options_pocket_label": "पॉकेट में सहेजे गए पृष्ठ",
"prefs_snippets_description": "Mozilla और Firefox से अद्यतन", "prefs_snippets_description": "Mozilla और Firefox से अद्यतन",
"settings_pane_button_label": "अपने नए टैब पृष्ठ को अनुकूलित करें", "settings_pane_button_label": "अपने नए टैब पृष्ठ को अनुकूलित करें",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Picatz vòstra adreça electronica", "firstrun_form_header": "Picatz vòstra adreça electronica",
"firstrun_form_sub_header": "per contunhar amb Firefox Sync.", "firstrun_form_sub_header": "per contunhar amb Firefox Sync.",
"firstrun_email_input_placeholder": "Adreça electronica", "firstrun_email_input_placeholder": "Adreça electronica",
"firstrun_invalid_input": "Valid email required", "firstrun_invalid_input": "Cal una adreça electronica valida",
"firstrun_extra_legal_links": "Se contunhatz, acceptatz las {terms} e l{privacy}.", "firstrun_extra_legal_links": "Se contunhatz, acceptatz las {terms} e l{privacy}.",
"firstrun_terms_of_service": "Condicions dutilizacion", "firstrun_terms_of_service": "Condicions dutilizacion",
"firstrun_privacy_notice": "Avís de privacitat", "firstrun_privacy_notice": "Avís de privacitat",

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Введите ваш адрес электронной почты", "firstrun_form_header": "Введите ваш адрес электронной почты",
"firstrun_form_sub_header": "чтобы продолжить использовать синхронизацию Firefox.", "firstrun_form_sub_header": "чтобы продолжить использовать синхронизацию Firefox.",
"firstrun_email_input_placeholder": "Эл. почта", "firstrun_email_input_placeholder": "Эл. почта",
"firstrun_invalid_input": "Valid email required", "firstrun_invalid_input": "Введите действующий адрес электронной почты",
"firstrun_extra_legal_links": "Продолжая, вы соглашаетесь с {terms} и {privacy}.", "firstrun_extra_legal_links": "Продолжая, вы соглашаетесь с {terms} и {privacy}.",
"firstrun_terms_of_service": "условиями службы", "firstrun_terms_of_service": "условиями службы",
"firstrun_privacy_notice": "политикой приватности", "firstrun_privacy_notice": "политикой приватности",

Просмотреть файл

@ -9,7 +9,7 @@ window.gActivityStreamStrings = {
"type_label_visited": "ප්‍රවේශිත", "type_label_visited": "ප්‍රවේශිත",
"type_label_bookmarked": "පිටු සලකුණු තැබූ", "type_label_bookmarked": "පිටු සලකුණු තැබූ",
"type_label_recommended": "Trending", "type_label_recommended": "Trending",
"type_label_pocket": "Saved to Pocket", "type_label_pocket": "Pocket හි සුරකින ලදී",
"type_label_downloaded": "Downloaded", "type_label_downloaded": "Downloaded",
"menu_action_bookmark": "පිටු සලකුණ", "menu_action_bookmark": "පිටු සලකුණ",
"menu_action_remove_bookmark": "පිටු සලකුණ ඉවත් කරන්න", "menu_action_remove_bookmark": "පිටු සලකුණ ඉවත් කරන්න",
@ -21,9 +21,9 @@ window.gActivityStreamStrings = {
"menu_action_unpin": "ඇමුණුම ඉවත් කරන්න", "menu_action_unpin": "ඇමුණුම ඉවත් කරන්න",
"confirm_history_delete_p1": "ඔබට මෙම පිටුවට අදාල සියලුම සිදුවීම් ඔබේ අතීතයන් මැකීමට අවශ්‍ය ද?", "confirm_history_delete_p1": "ඔබට මෙම පිටුවට අදාල සියලුම සිදුවීම් ඔබේ අතීතයන් මැකීමට අවශ්‍ය ද?",
"confirm_history_delete_notice_p2": "මෙම ක්‍රියාව අහෝසි කළ නොහැක.", "confirm_history_delete_notice_p2": "මෙම ක්‍රියාව අහෝසි කළ නොහැක.",
"menu_action_save_to_pocket": "Save to Pocket", "menu_action_save_to_pocket": "Pocket හි සුරකින්න",
"menu_action_delete_pocket": "Delete from Pocket", "menu_action_delete_pocket": "Pocket වෙතින් මකන්න",
"menu_action_archive_pocket": "Archive in Pocket", "menu_action_archive_pocket": "Pocket හි සංරක්ෂණ කරන්න",
"menu_action_show_file_mac_os": "Show in Finder", "menu_action_show_file_mac_os": "Show in Finder",
"menu_action_show_file_windows": "Open Containing Folder", "menu_action_show_file_windows": "Open Containing Folder",
"menu_action_show_file_linux": "Open Containing Folder", "menu_action_show_file_linux": "Open Containing Folder",
@ -38,14 +38,14 @@ window.gActivityStreamStrings = {
"section_disclaimer_topstories": "The most interesting stories on the web, selected based on what you read. From Pocket, now part of Mozilla.", "section_disclaimer_topstories": "The most interesting stories on the web, selected based on what you read. From Pocket, now part of Mozilla.",
"section_disclaimer_topstories_linktext": "එය ක්‍රියාකරන්නේ කෙසේදැයි අධ්‍යපනය කරන්න.", "section_disclaimer_topstories_linktext": "එය ක්‍රියාකරන්නේ කෙසේදැයි අධ්‍යපනය කරන්න.",
"section_disclaimer_topstories_buttontext": "හරි, තේරුණා", "section_disclaimer_topstories_buttontext": "හරි, තේරුණා",
"prefs_home_header": "Firefox Home Content", "prefs_home_header": "Firefox මුල්පිටු අන්තර්ගතය",
"prefs_home_description": "Choose what content you want on your Firefox Home screen.", "prefs_home_description": "Firefox මුල් පිටුවෙහි ඔබට අවැසි වන්නේ කුමන අන්තර්ගතයදැයි තෝරන්න.",
"prefs_section_rows_option": "{num} row;{num} rows", "prefs_section_rows_option": "{num} තීරය;{num} තීර",
"prefs_search_header": "Web Search", "prefs_search_header": "ජාල සෙවුම",
"prefs_topsites_description": "The sites you visit most", "prefs_topsites_description": "ඔබ වැඩිපුරම පිවිසෙන අඩවි",
"prefs_topstories_description2": "Great content from around the web, personalized for you", "prefs_topstories_description2": "Great content from around the web, personalized for you",
"prefs_topstories_options_sponsored_label": "Sponsored Stories", "prefs_topstories_options_sponsored_label": "Sponsored Stories",
"prefs_topstories_sponsored_learn_more": "Learn more", "prefs_topstories_sponsored_learn_more": "තවත් දැනගන්න",
"prefs_highlights_description": "A selection of sites that youve saved or visited", "prefs_highlights_description": "A selection of sites that youve saved or visited",
"prefs_highlights_options_visited_label": "Visited Pages", "prefs_highlights_options_visited_label": "Visited Pages",
"prefs_highlights_options_download_label": "Most Recent Download", "prefs_highlights_options_download_label": "Most Recent Download",
@ -60,7 +60,7 @@ window.gActivityStreamStrings = {
"edit_topsites_edit_button": "මෙම අඩවිය සකසන්න", "edit_topsites_edit_button": "මෙම අඩවිය සකසන්න",
"topsites_form_add_header": "නව ප්‍රමුඛ අඩවියක්", "topsites_form_add_header": "නව ප්‍රමුඛ අඩවියක්",
"topsites_form_edit_header": "ප්‍රමුඛ අඩවිය සකසන්න", "topsites_form_edit_header": "ප්‍රමුඛ අඩවිය සකසන්න",
"topsites_form_title_label": "Title", "topsites_form_title_label": "මාතෘකාව",
"topsites_form_title_placeholder": "සිරස්තල එක් කරන්න", "topsites_form_title_placeholder": "සිරස්තල එක් කරන්න",
"topsites_form_url_label": "URL", "topsites_form_url_label": "URL",
"topsites_form_image_url_label": "Custom Image URL", "topsites_form_image_url_label": "Custom Image URL",
@ -87,9 +87,9 @@ window.gActivityStreamStrings = {
"section_menu_action_manage_section": "Manage Section", "section_menu_action_manage_section": "Manage Section",
"section_menu_action_manage_webext": "Manage Extension", "section_menu_action_manage_webext": "Manage Extension",
"section_menu_action_add_topsite": "Add Top Site", "section_menu_action_add_topsite": "Add Top Site",
"section_menu_action_move_up": "Move Up", "section_menu_action_move_up": "ඉහළට ගෙනයන්න",
"section_menu_action_move_down": "Move Down", "section_menu_action_move_down": "පහළට ගෙනයන්න",
"section_menu_action_privacy_notice": "Privacy Notice", "section_menu_action_privacy_notice": "පෞද්ගලිකත්ව සටහන",
"firstrun_title": "Take Firefox with You", "firstrun_title": "Take Firefox with You",
"firstrun_content": "Get your bookmarks, history, passwords and other settings on all your devices.", "firstrun_content": "Get your bookmarks, history, passwords and other settings on all your devices.",
"firstrun_learn_more_link": "Learn more about Firefox Accounts", "firstrun_learn_more_link": "Learn more about Firefox Accounts",
@ -101,45 +101,5 @@ window.gActivityStreamStrings = {
"firstrun_terms_of_service": "Terms of Service", "firstrun_terms_of_service": "Terms of Service",
"firstrun_privacy_notice": "Privacy Notice", "firstrun_privacy_notice": "Privacy Notice",
"firstrun_continue_to_login": "Continue", "firstrun_continue_to_login": "Continue",
"firstrun_skip_login": "Skip this step", "firstrun_skip_login": "Skip this step"
"default_label_loading": "පූරණය වෙමින්…",
"header_stories": "ප්‍රමුඛ පුවත්",
"header_visit_again": "යළි පිවිසෙන්න",
"header_bookmarks": "නැවුම් පිටු සලකුණු",
"header_bookmarks_placeholder": "ඔබ සතුව තවම පිටුසලකුණු නැත.",
"header_stories_from": "සිට​",
"type_label_synced": "වෙනත් උපාංගයක් වෙතින් සමකාලීන​ කර ඇත​",
"type_label_open": "විවෘත",
"type_label_topic": "මාතෘකාව",
"type_label_now": "දැන්",
"menu_action_copy_address": "ලිපිනය පිටපත් කරන්න",
"menu_action_email_link": "විද්‍යුත් තැපැල් සබැඳි…",
"search_for_something_with": "{search_term} සදහා සෙවීමට භාවිත කළ යුත්තේ:",
"search_settings": "සෙවුම් සැකසුම් වෙනස් කරන්න",
"section_info_option": "තොරතුරු",
"section_info_send_feedback": "ප්‍රතිචාරය යවන්න",
"section_info_privacy_notice": "පෞද්ගලිකත්ව දැනුම්දීම්",
"welcome_title": "නව ටැබයට සාදරයෙන් පිළිගනිමු",
"welcome_body": "ඔබට පහසුවෙන් යළි භාවිතයට පහසු කරවීමට, Firefox මෙම ඉඩ ඔබට වඩාත් අදාල පිටු සළකුණු, ලිපි, විඩියෝ සහ ඔබ මෑතකදී පිවිසි පිටු පෙන්වීම සදහා භාවිත කරයි.",
"welcome_label": "ඔබේ ඉස්මතු කිරීම් හදුනාගනිමින්",
"time_label_less_than_minute": "<1m",
"time_label_minute": "{number} මිනිත්තු",
"time_label_hour": "{number}පැය",
"time_label_day": "{number}දින",
"settings_pane_header": "නව ටැබ අභිප්‍රේත",
"settings_pane_body2": "මෙම පිටුවේ ඔබ දැකිය යුතු දේ තෝරන්න.",
"settings_pane_search_header": "සොයන්න",
"settings_pane_search_body": "ඔබේ නව ටැබයෙන් වෙබ් සෙවීම.",
"settings_pane_topsites_body": "ඔබ නිරතුරුව පිවිසෙන වෙබ් අඩවි වෙත ප්‍රවේශය.",
"settings_pane_topsites_options_showmore": "පේළි දෙකක් පෙන්වන්න",
"settings_pane_bookmarks_header": "නැවුම් පිටු සලකුණු",
"settings_pane_bookmarks_body": "ඔබේ නැවුම් පිටු සලකුණු එක් ස්ථානයක.",
"settings_pane_visit_again_header": "යළි පිවිසෙන්න",
"settings_pane_highlights_options_visited": "පිවිසුණු අඩවි",
"settings_pane_topstories_options_sponsored": "අනුග්‍රහක පුවත් පෙන්වන්න",
"edit_topsites_showmore_button": "තවත් පෙන්වන්න",
"edit_topsites_showless_button": "අඩුවෙන් පෙන්වන්න",
"edit_topsites_done_button": "කළා",
"edit_topsites_dismiss_button": "මෙම අඩවිය ඉවත ලන්න",
"edit_topsites_add_button": "එක් කරන්න"
}; };

Просмотреть файл

@ -96,7 +96,7 @@ window.gActivityStreamStrings = {
"firstrun_form_header": "Zadajte e-mailovú adresu", "firstrun_form_header": "Zadajte e-mailovú adresu",
"firstrun_form_sub_header": "a používajte službu Firefox Sync.", "firstrun_form_sub_header": "a používajte službu Firefox Sync.",
"firstrun_email_input_placeholder": "E-mail", "firstrun_email_input_placeholder": "E-mail",
"firstrun_invalid_input": "Valid email required", "firstrun_invalid_input": "Vyžaduje sa platná e-mailová adresa",
"firstrun_extra_legal_links": "Pokračovaním súhlasíte s {terms} a {privacy}.", "firstrun_extra_legal_links": "Pokračovaním súhlasíte s {terms} a {privacy}.",
"firstrun_terms_of_service": "podmienkami používania služby", "firstrun_terms_of_service": "podmienkami používania služby",
"firstrun_privacy_notice": "zásadami ochrany súkromia", "firstrun_privacy_notice": "zásadami ochrany súkromia",

Просмотреть файл

@ -12,7 +12,6 @@ import {_ASRouter} from "lib/ASRouter.jsm";
const FAKE_PROVIDERS = [FAKE_LOCAL_PROVIDER, FAKE_REMOTE_PROVIDER]; const FAKE_PROVIDERS = [FAKE_LOCAL_PROVIDER, FAKE_REMOTE_PROVIDER];
const ALL_MESSAGE_IDS = [...FAKE_LOCAL_MESSAGES, ...FAKE_REMOTE_MESSAGES].map(message => message.id); const ALL_MESSAGE_IDS = [...FAKE_LOCAL_MESSAGES, ...FAKE_REMOTE_MESSAGES].map(message => message.id);
const FAKE_BUNDLE = [FAKE_LOCAL_MESSAGES[1], FAKE_LOCAL_MESSAGES[2]]; const FAKE_BUNDLE = [FAKE_LOCAL_MESSAGES[1], FAKE_LOCAL_MESSAGES[2]];
// Creates a message object that looks like messages returned by // Creates a message object that looks like messages returned by
// RemotePageManager listeners // RemotePageManager listeners
function fakeAsyncMessage(action) { function fakeAsyncMessage(action) {
@ -26,6 +25,8 @@ describe("ASRouter", () => {
let blockList; let blockList;
let fetchStub; let fetchStub;
let clock; let clock;
let getStringPrefStub;
let addObserverStub;
function createFakeStorage() { function createFakeStorage() {
return { return {
@ -47,6 +48,10 @@ describe("ASRouter", () => {
fetchStub = sandbox.stub(global, "fetch") fetchStub = sandbox.stub(global, "fetch")
.withArgs("http://fake.com/endpoint") .withArgs("http://fake.com/endpoint")
.resolves({ok: true, status: 200, json: () => Promise.resolve({messages: FAKE_REMOTE_MESSAGES})}); .resolves({ok: true, status: 200, json: () => Promise.resolve({messages: FAKE_REMOTE_MESSAGES})});
getStringPrefStub = sandbox.stub(global.Services.prefs, "getStringPref");
getStringPrefStub.returns("http://fake.com/endpoint");
addObserverStub = sandbox.stub(global.Services.prefs, "addObserver");
await createRouterAndInit(); await createRouterAndInit();
}); });
afterEach(() => { afterEach(() => {
@ -67,6 +72,10 @@ describe("ASRouter", () => {
const [, listenerAdded] = channel.addMessageListener.firstCall.args; const [, listenerAdded] = channel.addMessageListener.firstCall.args;
assert.isFunction(listenerAdded); assert.isFunction(listenerAdded);
}); });
it("should add an observer for each provider with a defined endpointPref", () => {
assert.calledOnce(addObserverStub);
assert.calledWith(addObserverStub, "remotePref");
});
it("should set state.blockList to the block list in persistent storage", async () => { it("should set state.blockList to the block list in persistent storage", async () => {
blockList = ["MESSAGE_ID"]; blockList = ["MESSAGE_ID"];
@ -85,6 +94,23 @@ describe("ASRouter", () => {
assert.isArray(Router.state.messages); assert.isArray(Router.state.messages);
assert.lengthOf(Router.state.messages, FAKE_LOCAL_MESSAGES.length + FAKE_REMOTE_MESSAGES.length); assert.lengthOf(Router.state.messages, FAKE_LOCAL_MESSAGES.length + FAKE_REMOTE_MESSAGES.length);
}); });
it("should call loadMessagesFromAllProviders on pref endpoint change", async () => {
sandbox.spy(Router, "loadMessagesFromAllProviders");
await Router.observe();
assert.calledOnce(Router.loadMessagesFromAllProviders);
});
it("should update provider url on pref change", async () => {
getStringPrefStub.withArgs("remotePref").returns("baz.com");
const {length} = Router.state.providers;
await Router.observe("", "", "remotePref");
const provider = Router.state.providers.find(p => p.url === "baz.com");
assert.lengthOf(Router.state.providers, length);
assert.isDefined(provider);
});
}); });
describe("#loadMessagesFromAllProviders", () => { describe("#loadMessagesFromAllProviders", () => {
@ -95,6 +121,15 @@ describe("ASRouter", () => {
} }
} }
it("should load provider endpoint based on pref", async () => {
getStringPrefStub.reset();
getStringPrefStub.returns("example.com");
await createRouterAndInit();
assert.calledOnce(getStringPrefStub);
assert.calledWithExactly(getStringPrefStub, "remotePref", "");
assert.isDefined(Router.state.providers.find(p => p.url === "example.com"));
});
it("should not trigger an update if not enough time has passed for a provider", async () => { it("should not trigger an update if not enough time has passed for a provider", async () => {
await createRouterAndInit([ await createRouterAndInit([
{id: "remotey", type: "remote", url: "http://fake.com/endpoint", updateCycleInMs: 300} {id: "remotey", type: "remote", url: "http://fake.com/endpoint", updateCycleInMs: 300}

Просмотреть файл

@ -73,7 +73,7 @@ describe("ASRouterFeed", () => {
prefs[EXPERIMENT_PREF] = true; prefs[EXPERIMENT_PREF] = true;
// call .onAction with INIT // call .onAction with INIT
feed.onAction({type: at.INIT}); feed.onAction({type: at.INIT, data: {name: EXPERIMENT_PREF}});
assert.notCalled(Router.init); assert.notCalled(Router.init);
}); });

Просмотреть файл

@ -14,7 +14,7 @@ export const FAKE_LOCAL_PROVIDER = {id: "onboarding", type: "local", messages: F
export const FAKE_REMOTE_MESSAGES = [ export const FAKE_REMOTE_MESSAGES = [
{id: "qux", template: "simple_template", content: {title: "Qux", body: "hello world"}} {id: "qux", template: "simple_template", content: {title: "Qux", body: "hello world"}}
]; ];
export const FAKE_REMOTE_PROVIDER = {id: "remotey", type: "remote", url: "http://fake.com/endpoint"}; export const FAKE_REMOTE_PROVIDER = {id: "remotey", type: "remote", url: "http://fake.com/endpoint", endpointPref: "remotePref"};
// Stubs methods on RemotePageManager // Stubs methods on RemotePageManager
export class FakeRemotePageManager { export class FakeRemotePageManager {