diff options
author | Peter Bengtsson <mail@peterbe.com> | 2021-07-15 12:59:34 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-15 12:59:34 -0400 |
commit | 3601b7bb982e958927e069715cfe07430bce7196 (patch) | |
tree | d305ecdbf80ce8126386a0d7886f70d915277c7c /files/es/mozilla/add-ons | |
parent | 9ace67d06f2369e3c770e3a11e06e1c8cc9f66fd (diff) | |
download | translated-content-3601b7bb982e958927e069715cfe07430bce7196.tar.gz translated-content-3601b7bb982e958927e069715cfe07430bce7196.tar.bz2 translated-content-3601b7bb982e958927e069715cfe07430bce7196.zip |
delete pages that were never translated from en-US (es, part 1) (#1547)
Diffstat (limited to 'files/es/mozilla/add-ons')
3 files changed, 0 insertions, 708 deletions
diff --git a/files/es/mozilla/add-ons/webextensions/api/webnavigation/index.html b/files/es/mozilla/add-ons/webextensions/api/webnavigation/index.html deleted file mode 100644 index d561c6d796..0000000000 --- a/files/es/mozilla/add-ons/webextensions/api/webnavigation/index.html +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: webNavigation -slug: Mozilla/Add-ons/WebExtensions/API/webNavigation -translation_of: Mozilla/Add-ons/WebExtensions/API/webNavigation ---- -<div>{{AddonSidebar}}</div> - -<p>Add event listeners for the various stages of a navigation. A navigation consists of a frame in the browser transitioning from one URL to another, usually (but not always) in response to a user action like clicking a link or entering a URL in the location bar.</p> - -<p>Compared with the {{WebExtAPIRef("webRequest")}} API: navigations usually result in the browser making web requests, but the webRequest API is concerned with the lower-level view from the HTTP layer, while the webNavigation API is more concerned with the view from the browser UI itself.</p> - -<p>Each event corresponds to a particular stage in the navigation. The sequence of events is like this:</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/13374/we-flow.png" style="display: block; height: 562px; margin-left: auto; margin-right: auto; width: 745px;"></p> - -<ul> - <li>The primary flow is: - <ul> - <li><code>{{WebExtAPIRef("webNavigation.onBeforeNavigate", "onBeforeNavigate")}}</code></li> - <li><code>{{WebExtAPIRef("webNavigation.onCommitted", "onCommitted")}}</code></li> - <li><code>{{WebExtAPIRef("webNavigation.onDOMContentLoaded", "onDOMContentLoaded")}}</code></li> - <li><code>{{WebExtAPIRef("webNavigation.onCompleted", "onCompleted")}}</code>.</li> - </ul> - </li> - <li>Additionally: - <ul> - <li><code>{{WebExtAPIRef("webNavigation.onCreatedNavigationTarget", "onCreatedNavigationTarget")}}</code> is fired before <code>onBeforeNavigate</code> if the browser needed to create a new tab or window for the navigation (for example, because the user opened a link in a new tab).</li> - <li>{{WebExtAPIRef("webNavigation.onHistoryStateUpdated", "onHistoryStateUpdated")}} is fired if a page uses the <a href="http://diveintohtml5.info/history.html">history API</a> to update the URL displayed in the browser's location bar.</li> - <li>{{WebExtAPIRef("webNavigation.onReferenceFragmentUpdated", "onReferenceFragmentUpdated")}} is fired if the <a href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> for a page is changed.</li> - <li>{{WebExtAPIRef("webNavigation.onErrorOccurred", "onErrorOccurred")}} can be fired at any point.</li> - </ul> - </li> -</ul> - -<p>Each navigation is a URL transition in a particular browser frame. The browser frame is identified by a tab ID and a frame ID. The frame may be the top-level browsing context in the tab, or may be a nested browsing context implemented as an <a href="/en-US/docs/Web/HTML/Element/iframe">iframe</a>.</p> - -<p>Each event's <code>addListener()</code> call accepts an optional filter parameter. The filter will specify one or more URL patterns, and the event will then only be fired for navigations in which the target URL matches one of the patterns.</p> - -<p>The <code>onCommitted</code> event listener is passed two additional properties: a {{WebExtAPIRef("webNavigation.TransitionType","TransitionType")}} indicating the cause of the navigation (for example, because the user clicked a link, or because the user selected a bookmark), and a {{WebExtAPIRef("webNavigation.TransitionQualifier","TransitionQualifier")}} providing further information about the navigation.</p> - -<p>To use this API you need to have the "webNavigation" <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.</p> - -<h2 id="Types">Types</h2> - -<dl> - <dt>{{WebExtAPIRef("webNavigation.TransitionType")}}</dt> - <dd>Cause of the navigation: for example, the user clicked a link, or typed an address, or clicked a bookmark.</dd> - <dt>{{WebExtAPIRef("webNavigation.TransitionQualifier")}}</dt> - <dd> - <div>Extra information about a transition.</div> - </dd> -</dl> - -<h2 id="Functions">Functions</h2> - -<dl> - <dt>{{WebExtAPIRef("webNavigation.getFrame()")}}</dt> - <dd>Retrieves information about a particular frame. A frame may be the top-level frame in a tab or a nested <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe">iframe</a>, and is uniquely identified by a tab ID and a frame ID.</dd> - <dt>{{WebExtAPIRef("webNavigation.getAllFrames()")}}</dt> - <dd> - <p>Given a tab ID, retrieves information about all the frames it contains.</p> - </dd> -</dl> - -<h2 id="Events">Events</h2> - -<dl> - <dt>{{WebExtAPIRef("webNavigation.onBeforeNavigate")}}</dt> - <dd> - <p>Fired when the browser is about to start a navigation event.</p> - </dd> - <dt>{{WebExtAPIRef("webNavigation.onCommitted")}}</dt> - <dd>Fired when a navigation is committed. At least part of the new document has been received from the server and the browser has decided to switch to the new document.</dd> - <dt>{{WebExtAPIRef("webNavigation.onDOMContentLoaded")}}</dt> - <dd>Fired when the <a href="https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded">DOMContentLoaded</a> event is fired in the page.</dd> - <dt>{{WebExtAPIRef("webNavigation.onCompleted")}}</dt> - <dd>Fired when a document, including the resources it refers to, is completely loaded and initialized. This is equivalent to the DOM <code><a href="https://developer.mozilla.org/en-US/docs/Web/Events/load">load</a></code> event.</dd> - <dt>{{WebExtAPIRef("webNavigation.onErrorOccurred")}}</dt> - <dd>Fired when an error occurs and the navigation is aborted. This can happen if either a network error occurred, or the user aborted the navigation.</dd> - <dt>{{WebExtAPIRef("webNavigation.onCreatedNavigationTarget")}}</dt> - <dd>Fired when a new window, or a new tab in an existing window, is created to host a navigation: for example, if the user opens a link in a new tab.</dd> - <dt>{{WebExtAPIRef("webNavigation.onReferenceFragmentUpdated")}}</dt> - <dd>Fired if the <a class="external-icon external" href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> for a page is changed.</dd> - <dt>{{WebExtAPIRef("webNavigation.onTabReplaced")}}</dt> - <dd> - <p>Fired when the contents of the tab is replaced by a different (usually previously pre-rendered) tab.</p> - </dd> - <dt>{{WebExtAPIRef("webNavigation.onHistoryStateUpdated")}}</dt> - <dd>Fired when the page used the <a class="external external-icon" href="http://diveintohtml5.info/history.html">history API</a> to update the URL displayed in the browser's location bar.</dd> -</dl> - -<h2 id="Browser_compatibility">Browser compatibility</h2> - -<p>{{Compat("webextensions.api.webNavigation")}}</p> - -<div class="hidden note"> -<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p> - -<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p> -</div> - -<h3 id="Edge_incompatibilities">Edge incompatibilities</h3> - -<p>Promises are not supported in Edge. Use callbacks instead.</p> - -<p>{{WebExtExamples("h2")}}</p> - -<div class="note"><strong>Acknowledgements</strong> - -<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/webNavigation"><code>chrome.webNavigation</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/web_navigation.json"><code>web_navigation.json</code></a> in the Chromium code.</p> - -<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p> -</div> - -<div class="hidden"> -<pre>// Copyright 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -</pre> -</div> diff --git a/files/es/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html b/files/es/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html deleted file mode 100644 index 426aeae50f..0000000000 --- a/files/es/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: Extending the developer tools -slug: Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools -translation_of: Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools ---- -<div>{{AddonSidebar}}</div> - -<div class="note"> -<p>This page describes devtools APIs as they exist in Firefox 55. Although the APIs are based on the <a href="https://developer.chrome.com/extensions/devtools">Chrome devtools APIs</a>, there are still many features that are not yet implemented in Firefox, and therefore are not documented here. To see which features are currently missing please see <a href="/en-US/Add-ons/WebExtensions/Using_the_devtools_APIs#Limitations_of_the_devtools_APIs">Limitations of the devtools APIs</a>.</p> -</div> - -<p><span class="seoSummary">You can use WebExtensions APIs to extend the browser's built-in developer tools.</span> To create a devtools extension, include the "<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/devtools_page">devtools_page</a>" key in <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a>:</p> - -<pre class="brush: json notranslate">"devtools_page": "devtools/devtools-page.html"</pre> - -<p>The value of this key is a URL pointing to an HTML file that's been bundled with your extension. The URL should be relative to the manifest.json file itself.</p> - -<p>The HTML file defines a special page in the extension, called the devtools page.</p> - -<h2 id="The_devtools_page">The devtools page</h2> - -<p>The devtools page is loaded when the browser devtools are opened, and unloaded when it is closed. Note that because the devtools window is associated with a single tab, it's quite possible for more than one devtools window - hence more than one devtools page - to exist at the same time.</p> - -<p>The devtools page doesn't have any visible DOM, but can include JavaScript sources using <code><a href="/en-US/docs/Web/HTML/Element/script"><script></a></code> tags. The sources must be bundled with the extension itself. The sources get access to:</p> - -<ul> - <li>The normal DOM APIs accessible through the global <code><a href="/en-US/docs/Web/API/Window">window</a></code> object</li> - <li>The same <a href="/en-US/Add-ons/WebExtensions/Content_scripts#WebExtension_APIs">WebExtension APIs as in Content Scripts</a></li> - <li>The devtools APIs: - <ul> - <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow">devtools.inspectedWindow</a></code></li> - <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.network">devtools.network</a></code></li> - <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.panels">devtools.panels</a></code></li> - </ul> - </li> -</ul> - -<p>Note that the devtools page does not get access to any other WebExtension APIs, and the background page doesn't get access to the devtools APIs. Instead, the devtools page and the background page must communicate using the <code>runtime</code> messaging APIs. Here's an example:</p> - -<pre class="brush: html notranslate"><!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - </head> - <body> - <script src="devtools.js"></script> - </body> -</html></pre> - -<p>The devtools.js file will hold the actual code creating your dev tools extensions.</p> - -<h2 id="Creating_panels">Creating panels</h2> - -<p>The devtools window hosts a number of separate tools - the JavaScript Debugger, Network Monitor, and so on. A row of tabs across the top lets the user switch between the different tools. The window hosting each tool's user interface is called a "panel".</p> - -<p>Using the <code>devtools.panels.create()</code> API, you can create your own panel in the devtools window:</p> - -<pre class="brush: js notranslate">browser.devtools.panels.create( - "My Panel", // title - "icons/star.png", // icon - "devtools/panel/panel.html" // content -).then((newPanel) => { - newPanel.onShown.addListener(initialisePanel); - newPanel.onHidden.addListener(unInitialisePanel); -});</pre> - -<p>This takes three mandatory arguments: the panel's title, icon, and content. It returns a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> which resolves to a <code>devtools.panels.ExtensionPanel</code> object representing the new panel.</p> - -<h2 id="Interacting_with_the_target_window">Interacting with the target window</h2> - -<p>The developer tools are always attached to a particular browser tab. This is referred to as the "target" for the developer tools, or the "inspected window". You can interact with the inspected window using the <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow">devtools.inspectedWindow</a></code> API.</p> - -<h3 id="Running_code_in_the_target_window">Running code in the target window</h3> - -<p>The <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow/eval">devtools.inspectedWindow.eval()</a></code> provides one way to run code in the inspected window.</p> - -<p>This is somewhat like using {{WebExtAPIRef("tabs.executeScript()")}} to inject a content script, but with one important difference:</p> - -<ul> - <li>unlike content scripts, scripts loaded using <code>devtools.inspectedWindow.eval()</code><strong> do not</strong> get <a href="/en-US/Add-ons/WebExtensions/Content_scripts#DOM_access">a "clean view of the DOM"</a>: that is, they can see changes to the page made by page scripts.</li> -</ul> - -<div class="note"> -<p>Note that a clean view of the DOM is a security feature, intended to help prevent hostile pages from tricking extensions by redefining the behavior of native DOM functions. This means you need to be very careful using eval(), and should use a normal content script if you can.</p> -</div> - -<p>Scripts loaded using <code>devtools.inspectedWindow.eval()</code> also don't see any JavaScript variables defined by content scripts.</p> - -<h3 id="Working_with_content_scripts">Working with content scripts</h3> - -<p>A devtools document doesn't have direct access to {{WebExtAPIRef("tabs.executeScript()")}}, so if you need to inject a content script, the devtools document must send a message to the background script asking it to inject the script. The <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow/tabId">devtools.inspectedWindow.tabId</a></code> provides the ID of the target tab: the devtools document can pass this to the background script, and the background script can in turn pass it into {{WebExtAPIRef("tabs.executeScript()")}}:</p> - -<pre class="brush: js notranslate">// devtools-panel.js - -const scriptToAttach = "document.body.innerHTML = 'Hi from the devtools';"; - -window.addEventListener("click", () => { - browser.runtime.sendMessage({ - tabId: browser.devtools.inspectedWindow.tabId, - script: scriptToAttach - }); -});</pre> - -<pre class="brush: js notranslate">// background.js - -function handleMessage(request, sender, sendResponse) { - browser.tabs.executeScript(request.tabId, { - code: request.script - }); -} - -browser.runtime.onMessage.addListener(handleMessage);</pre> - -<p>If you need to exchange messages between the content scripts running in the target window and a devtools document, it's a good idea to use the {{WebExtAPIRef("runtime.connect()")}} and {{WebExtAPIRef("runtime.onConnect")}} to set up a connection between the background page and the devtools document. The background page can then maintain a mapping between tab IDs and {{WebExtAPIRef("runtime.Port")}} objects, and use this to route messages between the two scopes.</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/14923/devtools-content-scripts.png" style="display: block; height: 416px; margin-left: auto; margin-right: auto; width: 600px;"></p> - -<h2 id="Limitations_of_the_devtools_APIs">Limitations of the devtools APIs</h2> - -<p>These APIs are based on the Chrome devtools APIs, but many features are still missing, compared with Chrome. This section lists the features that are still not implemented, as of Firefox 54. Note that the devtools APIs are under active development and we expect to add support for most of them in future releases.</p> - -<h3 id="devtools.inspectedWindow">devtools.inspectedWindow</h3> - -<p>The following are not supported:</p> - -<ul> - <li><code>inspectedWindow.getResources()</code></li> - <li><code>inspectedWindow.onResourceAdded</code></li> - <li><code>inspectedWindow.onResourceContentCommitted</code></li> -</ul> - -<p>None of the options to <code>inspectedWindow.eval()</code> are supported.</p> - -<p>Scripts injected using <code>inspectedWindow.eval()</code> can't use all the Console's command-line helper functions, but <code>$0</code> and <code>inspect(...)</code> are both supported (starting from Firefox 55).</p> - -<h3 id="devtools.panels">devtools.panels</h3> - -<p>The following are not supported:</p> - -<ul> - <li><code>panels.elements</code></li> - <li><code>panels.sources</code></li> - <li><code>panels.setOpenResourceHandler()</code></li> - <li><code>panels.openResource()</code></li> - <li><code>panels.ExtensionPanel.createStatusBarButton()</code></li> - <li><code>panels.Button</code></li> - <li><code>panels.ElementsPanel</code></li> - <li><code>panels.SourcesPanel</code></li> -</ul> - -<h2 id="Examples">Examples</h2> - -<p>The <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> repo on GitHub, contains several examples of extensions that use devtools panels:</p> - -<ul> - <li> - <p><a href="https://github.com/mdn/webextensions-examples/blob/master/devtools-panels/">devtools-panels</a> use devtools panels:</p> - </li> -</ul> diff --git a/files/es/mozilla/add-ons/webextensions/internationalization/index.html b/files/es/mozilla/add-ons/webextensions/internationalization/index.html deleted file mode 100644 index 89c542a2e7..0000000000 --- a/files/es/mozilla/add-ons/webextensions/internationalization/index.html +++ /dev/null @@ -1,405 +0,0 @@ ---- -title: Internationalization -slug: Mozilla/Add-ons/WebExtensions/Internationalization -translation_of: Mozilla/Add-ons/WebExtensions/Internationalization ---- -<pre class="brush: html notranslate"><span class="seoSummary"><kbd>H</kbd></span></pre> - -<p>The <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions">WebExtensions</a> API has a rather handy module available for internationalizing extensions — <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n">i18n</a>. In this article we'll explore its features and provide a practical example of how it works. The i18n system for extensions built using WebExtension APIs is similar to common JavaScript libraries for i18n such as <a href="http://i18njs.com/">i18n.js</a>.</p> - -<div class="note"> -<p>The example extension featured in this article — <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> — is available on GitHub. Follow along with the source code as you go through the sections below.</p> -</div> - -<h2 id="Anatomy_of_an_internationalized_extension">Anatomy of an internationalized extension</h2> - -<p>An internationalized extension can contain the same features as any other extension — <a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">background scripts</a>, <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">content scripts</a>, etc. — but it also has some extra parts to allow it to switch between different locales. These are summarized in the following directory tree:</p> - -<ul class="directory-tree"> - <li>extension-root-directory/ - <ul> - <li>_locales - <ul> - <li>en - <ul> - <li>messages.json - <ul> - <li>English messages (strings)</li> - </ul> - </li> - </ul> - </li> - <li>de - <ul> - <li>messages.json - <ul> - <li>German messages (strings)</li> - </ul> - </li> - </ul> - </li> - <li>etc.</li> - </ul> - </li> - <li>manifest.json - <ul> - <li>locale-dependent metadata</li> - </ul> - </li> - <li>myJavascript.js - <ul> - <li>JavaScript for retrieving browser locale, locale-specific messages, etc.</li> - </ul> - </li> - <li>myStyles.css - <ul> - <li>locale-dependent CSS</li> - </ul> - </li> - </ul> - </li> -</ul> - -<p>Let's explore each of the new features in turn — each of the below sections represents a step to follow when internationalizing your extension.</p> - -<h2 id="Providing_localized_strings_in__locales">Providing localized strings in _locales</h2> - -<div class="pull-aside"> -<div class="moreinfo">You can look up language subtags using the <em>Find</em> tool on the <a href="https://r12a.github.io/app-subtags/">Language subtag lookup page</a>. Note that you need to search for the English name of the language.</div> -</div> - -<p>Every i18n system requires the provision of strings translated into all the different locales you want to support. In extensions, these are contained within a directory called <code>_locales</code>, placed inside the extension root. Each individual locale has its strings (referred to as messages) contained within a file called <code>messages.json</code>, which is placed inside a subdirectory of <code>_locales</code>, named using the language subtag for that locale's language.</p> - -<p>Note that if the subtag includes a basic language plus a regional variant, then the language and variant are conventionally separated using a hyphen: for example, "en-US". However, in the directories under <code>_locales</code>, <strong>the separator must be an underscore</strong>: "en_US".</p> - -<p>So <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n/_locales">for example, in our sample app</a> we have directories for "en" (English), "de" (German), "nl" (Dutch), and "ja" (Japanese). Each one of these has a <code>messages.json</code> file inside it.</p> - -<p>Let's now look at the structure of one of these files (<a href="https://github.com/mdn/webextensions-examples/blob/master/notify-link-clicks-i18n/_locales/en/messages.json">_locales/en/messages.json</a>):</p> - -<pre class="brush: json notranslate">{ - "extensionName": { - "message": "Notify link clicks i18n", - "description": "Name of the extension." - }, - - "extensionDescription": { - "message": "Shows a notification when the user clicks on links.", - "description": "Description of the extension." - }, - - "notificationTitle": { - "message": "Click notification", - "description": "Title of the click notification." - }, - - "notificationContent": { - "message": "You clicked $URL$.", - "description": "Tells the user which link they clicked.", - "placeholders": { - "url" : { - "content" : "$1", - "example" : "https://developer.mozilla.org" - } - } - } -}</pre> - -<p>This file is standard JSON — each one of its members is an object with a name, which contains a <code>message</code> and a <code>description</code>. All of these items are strings; <code>$URL$</code> is a placeholder, which is replaced with a substring at the time the <code>notificationContent</code> member is called by the extension. You'll learn how to do this in the {{anch("Retrieving message strings from JavaScript")}} section.</p> - -<div class="note"> -<p><strong>Note</strong>: You can find much more information about the contents of <code>messages.json</code> files in our <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/Locale-Specific_Message_reference">Locale-Specific Message reference</a>.</p> -</div> - -<h2 id="Internationalizing_manifest.json">Internationalizing manifest.json</h2> - -<p>There are a couple of different tasks to carry out to internationalize your manifest.json.</p> - -<h3 id="Retrieving_localized_strings_in_manifests">Retrieving localized strings in manifests</h3> - -<p>Your <a href="https://github.com/mdn/webextensions-examples/blob/master/notify-link-clicks-i18n/manifest.json">manifest.json</a> includes strings that are displayed to the user, such as the extension's name and description. If you internationalize these strings and put the appropriate translations of them in messages.json, then the correct translation of the string will be displayed to the user, based on the current locale, like so.</p> - -<p>To internationalize strings, specify them like this:</p> - -<pre class="brush: json notranslate">"name": "__MSG_extensionName__", -"description": "__MSG_extensionDescription__",</pre> - -<p>Here, we are retrieving message strings dependant on the browser's locale, rather than just including static strings.</p> - -<p>To call a message string like this, you need to specify it like this:</p> - -<ol> - <li>Two underscores, followed by</li> - <li>The string "MSG", followed by</li> - <li>One underscore, followed by</li> - <li>The name of the message you want to call as defined in <code>messages.json</code>, followed by</li> - <li>Two underscores</li> -</ol> - -<pre class="notranslate"><strong>__MSG_</strong> + <em>messageName</em> + <strong>__</strong></pre> - -<h3 id="Specifying_a_default_locale">Specifying a default locale</h3> - -<p>Another field you should specify in your manifest.json is <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/default_locale">default_locale</a>:</p> - -<pre class="brush: json notranslate">"default_locale": "en"</pre> - -<p>This specifies a default locale to use if the extension doesn't include a localized string for the browser's current locale. Any message strings that are not available in the browser locale are taken from the default locale instead. There are some more details to be aware of in terms of how the browser selects strings — see {{anch("Localized string selection")}}.</p> - -<h2 id="Locale-dependent_CSS">Locale-dependent CSS</h2> - -<p>Note that you can also retrieve localized strings from CSS files in the extension. For example, you might want to construct a locale-dependent CSS rule, like this:</p> - -<pre class="brush: css notranslate">header { - background-image: url(../images/__MSG_extensionName__/header.png); -}</pre> - -<p>This is useful, although you might be better off handling such a situation using {{anch("Predefined messages")}}.</p> - -<h2 id="Retrieving_message_strings_from_JavaScript">Retrieving message strings from JavaScript</h2> - -<p>So, you've got your message strings set up, and your manifest. Now you just need to start calling your message strings from JavaScript so your extension can talk the right language as much as possible. The actual <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n">i18n API</a> is pretty simple, containing just four main methods:</p> - -<ul> - <li>You'll probably use {{WebExtAPIRef("i18n.getMessage()")}} most often — this is the method you use to retrieve a specific language string, as mentioned above. We'll see specific usage examples of this below.</li> - <li>The {{WebExtAPIRef("i18n.getAcceptLanguages()")}} and {{WebExtAPIRef("i18n.getUILanguage()")}} methods could be used if you needed to customize the UI depending on the locale — perhaps you might want to show preferences specific to the users' preferred languages higher up in a prefs list, or display cultural information relevant only to a certain language, or format displayed dates appropriately according to the browser locale.</li> - <li>The {{WebExtAPIRef("i18n.detectLanguage()")}} method could be used to detect the language of user-submitted content, and format it appropriately.</li> -</ul> - -<p>In our <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> example, the<a href="https://github.com/mdn/webextensions-examples/blob/master/notify-link-clicks-i18n/background-script.js"> background script</a> contains the following lines:</p> - -<pre class="brush: js notranslate">var title = browser.i18n.getMessage("notificationTitle"); -var content = browser.i18n.getMessage("notificationContent", message.url);</pre> - -<p>The first one just retrieves the <code>notificationTitle message</code> field from the available <code>messages.json</code> file most appropriate for the browser's current locale. The second one is similar, but it is being passed a URL as a second parameter. What gives? This is how you specify the content to replace the <code>$URL$</code> placeholder we see in the <code>notificationContent message</code> field:</p> - -<pre class="brush: json notranslate">"notificationContent": { - "message": "You clicked $URL$.", - "description": "Tells the user which link they clicked.", - "placeholders": { - "url" : { - "content" : "$1", - "example" : "https://developer.mozilla.org" - } - } -} -</pre> - -<p>The <code>"placeholders"</code> member defines all the placeholders, and where they are retrieved from. The <code>"url"</code> placeholder specifies that its content is taken from $1, which is the first value given inside the second parameter of <code>getMessage()</code>. Since the placeholder is called <code>"url"</code>, we use <code>$URL$</code> to call it inside the actual message string (so for <code>"name"</code> you'd use <code>$NAME$</code>, etc.) If you have multiple placeholders, you can provide them inside an array that is given to {{WebExtAPIRef("i18n.getMessage()")}} as the second parameter — <code>[a, b, c]</code> will be available as <code>$1</code>, <code>$2</code>, and <code>$3</code>, and so on, inside <code>messages.json</code>.</p> - -<p>Let's run through an example: the original <code>notificationContent</code> message string in the <code>en/messages.json</code> file is</p> - -<pre class="notranslate">You clicked $URL$.</pre> - -<p>Let's say the link clicked on points to <code>https://developer.mozilla.org</code>. After the {{WebExtAPIRef("i18n.getMessage()")}} call, the contents of the second parameter are made available in messages.json as <code>$1</code>, which replaces the <code>$URL$</code> placeholder as defined in the <code>"url"</code> placeholder. So the final message string is</p> - -<pre class="notranslate">You clicked https://developer.mozilla.org.</pre> - -<h3 id="Direct_placeholder_usage">Direct placeholder usage</h3> - -<p>It is possible to insert your variables (<code>$1</code>, <code>$2</code>, <code>$3</code>, etc.) directly into the message strings, for example we could rewrite the above <code>"notificationContent"</code> member like this:</p> - -<pre class="brush: json notranslate">"notificationContent": { - "message": "You clicked $1.", - "description": "Tells the user which link they clicked." -}</pre> - -<p>This may seem quicker and less complex, but the other way (using <code>"placeholders"</code>) is seen as best practice. This is because having the placeholder name (e.g. <code>"url"</code>) and example helps you to remember what the placeholder is for — a week after you write your code, you'll probably forget what <code>$1</code>–<code>$8</code> refer to, but you'll be more likely to know what your placeholder names refer to.</p> - -<h3 id="Hardcoded_substitution">Hardcoded substitution</h3> - -<p>It is also possible to include hardcoded strings in placeholders, so that the same value is used every time, instead of getting the value from a variable in your code. For example:</p> - -<pre class="brush: json notranslate">"mdn_banner": { - "message": "For more information on web technologies, go to $MDN$.", - "description": "Tell the user about MDN", - "placeholders": { - "mdn": { - "content": "https://developer.mozilla.org/" - } - } -}</pre> - -<p>In this case we are just hardcoding the placeholder content, rather than getting it from a variable value like <code>$1</code>. This can sometimes be useful when your message file is very complex, and you want to split up different values to make the strings more readable in the file, plus then these values could be accessed programmatically.</p> - -<p>In addition, you can use such substitutions to specify parts of the string that you don't want to be translated, such as person or business names.</p> - -<h2 id="Localized_string_selection">Localized string selection</h2> - -<p>Locales can be specified using only a language code, like <code>fr</code> or <code>en</code>, or they may be further qualified with a region code, like <code>en_US</code> or <code>en_GB</code>, which describes a regional variant of the same basic language. When you ask the i18n system for a string, it will select a string using the following algorithm:</p> - -<ol> - <li>if there is a <code>messages.json</code> file for the exact current locale, and it contains the string, return it.</li> - <li>Otherwise, if the current locale is qualified with a region (e.g. <code>en_US</code>) and there is a <code>messages.json</code> file for the regionless version of that locale (e.g. <code>en</code>), and that file contains the string, return it.</li> - <li>Otherwise, if there is a <code>messages.json</code> file for the <code>default_locale</code> defined in the <code>manifest.json</code>, and it contains the string, return it.</li> - <li>Otherwise return an empty string.</li> -</ol> - -<p>Take the following example:</p> - -<ul class="directory-tree"> - <li>extension-root-directory/ - <ul> - <li>_locales - <ul> - <li>en_GB - <ul> - <li>messages.json - <ul> - <li><code>{ "colorLocalised": { "message": "colour", "description": "Color." }, ... }</code></li> - </ul> - </li> - </ul> - en - - <ul> - <li>messages.json - <ul> - <li><code>{ "colorLocalised": { "message": "color", "description": "Color." }, ... }</code></li> - </ul> - </li> - </ul> - </li> - <li>fr - <ul> - <li>messages.json - <ul> - <li><code>{ "colorLocalised": { "message": "<span lang="fr">couleur</span>", "description": "Color." }, ...}</code></li> - </ul> - </li> - </ul> - </li> - </ul> - </li> - </ul> - </li> -</ul> - -<p>Suppose the <code>default_locale</code> is set to <code>fr</code>, and the browser's current locale is <code>en_GB</code>:</p> - -<ul> - <li>If the extension calls <code>getMessage("colorLocalised")</code>, it will return "colour".</li> - <li>If "colorLocalised" were not present in <code>en_GB</code>, then <code>getMessage("colorLocalised")</code>, would return "color", not "couleur".</li> -</ul> - -<h2 id="Predefined_messages">Predefined messages</h2> - -<p>The i18n module provides us with some predefined messages, which we can call in the same way as we saw earlier in {{anch("Calling message strings from manifests and extension CSS")}}. For example:</p> - -<pre class="notranslate">__MSG_extensionName__</pre> - -<p>Predefined messages use exactly the same syntax, except with <code>@@</code> before the message name, for example</p> - -<pre class="notranslate">__MSG_@@ui_locale__</pre> - -<p>The following table shows the different available predefined messages:</p> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Message name</th> - <th scope="col">Description</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>@@extension_id</code></td> - <td> - <p>The extension's internally-generated UUID. You might use this string to construct URLs for resources inside the extension. Even unlocalized extensions can use this message.</p> - - <p>You can't use this message in a manifest file.</p> - - <p>Also note that this ID is <em>not</em> the add-on ID returned by {{WebExtAPIRef("runtime.id")}}, and that can be set using the <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> key in manifest.json. It's the generated UUID that appears in the add-on's URL. This means that you can't use this value as the <code>extensionId</code> parameter to {{WebExtAPIRef("runtime.sendMessage()")}}, and can't use it to check against the <code>id</code> property of a {{WebExtAPIRef("runtime.MessageSender")}} object.</p> - </td> - </tr> - <tr> - <td><code>@@ui_locale</code></td> - <td>The current locale; you might use this string to construct locale-specific URLs.</td> - </tr> - <tr> - <td><code>@@bidi_dir</code></td> - <td>The text direction for the current locale, either "ltr" for left-to-right languages such as English or "rtl" for right-to-left languages such as Arabic.</td> - </tr> - <tr> - <td><code>@@bidi_reversed_dir</code></td> - <td>If the <code>@@bidi_dir</code> is "ltr", then this is "rtl"; otherwise, it's "ltr".</td> - </tr> - <tr> - <td><code>@@bidi_start_edge</code></td> - <td>If the <code>@@bidi_dir</code> is "ltr", then this is "left"; otherwise, it's "right".</td> - </tr> - <tr> - <td><code>@@bidi_end_edge</code></td> - <td>If the <code>@@bidi_dir</code> is "ltr", then this is "right"; otherwise, it's "left".</td> - </tr> - </tbody> -</table> - -<p>Going back to our earlier example, it would make more sense to write it like this:</p> - -<pre class="brush: css notranslate">header { - background-image: url(../images/__MSG_@@ui_locale__/header.png); -}</pre> - -<p>Now we can just store our local specific images in directories that match the different locales we are supporting — en, de, etc. — which makes a lot more sense.</p> - -<p>Let's look at an example of using <code>@@bidi_*</code> messages in a CSS file:</p> - -<pre class="brush: css notranslate">body { - direction: __MSG_@@bidi_dir__; -} - -div#header { - margin-bottom: 1.05em; - overflow: hidden; - padding-bottom: 1.5em; - padding-__MSG_@@bidi_start_edge__: 0; - padding-__MSG_@@bidi_end_edge__: 1.5em; - position: relative; -}</pre> - -<p>For left-to-right languages such as English, the CSS declarations involving the predefined messages above would translate to the following final code lines:</p> - -<pre class="brush: css notranslate">direction: ltr; -padding-left: 0; -padding-right: 1.5em; -</pre> - -<p>For a right-to-left language like Arabic, you'd get:</p> - -<pre class="brush: css notranslate">direction: rtl; -padding-right: 0; -padding-left: 1.5em;</pre> - -<h2 id="Testing_out_your_extension">Testing out your extension</h2> - -<p>Starting in Firefox 45, you can install extensions temporarily from disk — see <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Packaging_and_installation#Loading_from_disk">Loading from disk</a>. Do this, and then try testing out our <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> extension. Go to one of your favourite websites and click a link to see if a notification appears reporting the URL of the clicked link.</p> - -<p>Next, change Firefox's locale to one supported in the extension that you want to test.</p> - -<ol> - <li>Open "about:config" in Firefox, and search for the <code>intl.locale.requested</code> preference (bear in mind that before Firefox 59, this pref is called <code>general.useragent.locale</code>).</li> - <li>If the preference exists, double-click it (or press Return/Enter) to select it, enter the language code for the locale you want to test, then click "OK" (or press Return/Enter). For example in our example extension, "en" (English), "de" (German), "nl" (Dutch), and "ja" (Japanese) are supported. You can also set the value to an empty string (<code>""</code>), which will cause the browser to use the OS default locale.</li> - <li>If the <code>intl.locale.requested</code> preference does not exist, right-click the list of preferences (or activate the context menu using the keyboard), and choose "New" followed by "String". Enter <code>intl.locale.requested</code> for the preference name and, "de", or "nl", etc. for the preference value, as described in step 2 above.</li> - <li>Search for <code>intl.locale.matchOS</code> and, if the preference exists and has the value <code>true</code>, double-click it so that it is set to <code>false</code>.</li> - <li>Restart your browser to complete the change.</li> -</ol> - -<div class="note"> -<p><strong>Note</strong>: This works to change the browser's locale, even if you haven't got the <a href="https://addons.mozilla.org/en-US/firefox/language-tools/">language pack</a> installed for that language. You'll just get the browser UI in your default language if this is the case.</p> -</div> - -<ol> -</ol> - -<div class="note"> -<p><strong>Note:</strong> To change the result of <code>getUILanguage</code> the language pack is required, since it reflects the browser UI language and not the language used for extension messages.</p> -</div> - -<p>Load the extension temporarily from disk again, then test your new locale:</p> - -<ul> - <li>Visit "about:addons" again — you should now see the extension listed, with its icon, plus name and description in the chosen language.</li> - <li>Test your extension again. In our example, you'd go to another website and click a link, to see if the notification now appears in the chosen language.</li> -</ul> - -<p>{{EmbedYouTube("R7--fp5pPGg")}}</p> |