Merge comm-central to ash
This commit is contained in:
Коммит
4758969d5e
2
.hgtags
2
.hgtags
|
@ -141,3 +141,5 @@ fdf6e7ccc0aaef99cba75d02c58b8fdca45b150a NIGHTLY_103_END
|
|||
5e8f22244df03dfd4eb383a8688df44cd2d24752 NIGHTLY_108_END
|
||||
21ce17b950114437f716947e460a1dff0cd041fa BETA_109_BASE
|
||||
c085c6203989d620f77410fc207ab04f625f09cd NIGHTLY_109_END
|
||||
ae431256747870c95941817df69666a383f0545a BETA_110_BASE
|
||||
31883a704fda918f2ef5fc4c544126eeb81f2f5d NIGHTLY_110_END
|
||||
|
|
|
@ -12,6 +12,8 @@ Thunderbird Source Tree Documentation
|
|||
|
||||
mots/index
|
||||
|
||||
l10n/index
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
# Migrating Strings to Fluent Files
|
||||
|
||||
Like [Firefox](https://firefox-source-docs.mozilla.org/l10n/migrations/index.html),
|
||||
Thunderbird developers are working on migrating strings from legacy formats to
|
||||
Fluent. The process is very similar to how migrations are done for Firefox. The
|
||||
differences are detailed below.
|
||||
|
||||
## Migration Recipes
|
||||
|
||||
When part of Thunderbird’s UI is migrated to Fluent, a migration recipe should
|
||||
be included in the same patch that adds new strings to .ftl files. Recipies are
|
||||
stored in [comm-central](https://hg.mozilla.org/comm-central/file/tip/python/l10n/tb_fluent_migrations).
|
||||
After a patch with migrations landed, it will be run for all locales as part of
|
||||
the [Thunderbird Cross-Channel string quarantining process](cross_channel.md).
|
||||
|
||||
Be sure to read [Migrating Legacy Formats](https://firefox-source-docs.mozilla.org/l10n/migrations/legacy.html)
|
||||
along with the below example.
|
||||
|
||||
The migration recipe’s filename should start with a reference to the associated
|
||||
bug number, and include a brief description of the bug, e.g. `bug_1805746_calendar_view.py`
|
||||
for the below example.
|
||||
|
||||
### Example: Migrate Multiple DTD strings to Fluent
|
||||
|
||||
Often, strings are migrated as part of ongoing UI work to convert XUL code
|
||||
to HTML. Multiple DTD strings may convert to a single Fluent string with
|
||||
attributes. It really depends on the document structure and what the UI changes
|
||||
are doing.
|
||||
|
||||
**Legacy strings are in `comm/calendar/locales/en-US/chrome/calendar/calendar.dtd`**
|
||||
|
||||
```dtd
|
||||
<!ENTITY calendar.day.button.tooltip "Switch to day view" >
|
||||
<!ENTITY calendar.day.button.label "Day" >
|
||||
```
|
||||
|
||||
**The (simplified) XUL code**
|
||||
|
||||
```xml
|
||||
<radio id="calendar-day-view-button"
|
||||
label="&calendar.day.button.label;"
|
||||
tooltiptext="&calendar.day.button.tooltip;" />
|
||||
```
|
||||
|
||||
**The new HTML**
|
||||
|
||||
```html
|
||||
<button id="calTabDay" data-l10n-id="calendar-view-toggle-day"></button>
|
||||
```
|
||||
|
||||
**The new FTL string**
|
||||
|
||||
```fluent
|
||||
calendar-view-toggle-day = Day
|
||||
.title = Switch to day view
|
||||
```
|
||||
|
||||
**Renders as:**
|
||||
|
||||
```html
|
||||
<button id="calTabDay" title="Switch to day view">Day</button>
|
||||
```
|
||||
|
||||
This case migrates two DTD strings, `calendar.day.button.label` and `calendar.day.button.tooltip`
|
||||
to create a single FTL string, `calendar-view-toggle-day`, with one (`title`)
|
||||
attribute.
|
||||
|
||||
**The migration recipe:**
|
||||
|
||||
```python
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
from fluent.migrate.helpers import transforms_from
|
||||
from fluent.migrate import COPY
|
||||
|
||||
def migrate(ctx):
|
||||
"""Bug 1805746 - Update Calendar View selection part {index}."""
|
||||
target = "calendar/calendar/calendar-widgets.ftl"
|
||||
reference = "calendar/calendar/calendar-widgets.ftl"
|
||||
|
||||
ctx.add_transforms(
|
||||
target,
|
||||
reference,
|
||||
transforms_from(
|
||||
"""
|
||||
calendar-view-toggle-day = { COPY(from_path, "calendar.day.button.label") }
|
||||
.title = { COPY(from_path, "calendar.day.button.tooltip") }
|
||||
""",
|
||||
from_path="calendar/chrome/calendar/calendar.dtd",
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
Migrations are Python modules, and implement
|
||||
a single `migrate(MigrationContext)` function. The `migrate()` function makes
|
||||
calls into `MigrationContext.add_transforms()`.
|
||||
|
||||
The `add_transforms()` function takes three arguments:
|
||||
- `target_path`: Path to the target l10n file
|
||||
- `reference_path`: Path to the reference (en-US) file
|
||||
- A list of Transforms
|
||||
|
||||
```{note}
|
||||
For Thunderbird migrations, the target and reference path are the same.
|
||||
```
|
||||
|
||||
Transforms are rather dense AST nodes. See
|
||||
[Transforms](https://firefox-source-docs.mozilla.org/l10n/migrations/overview.html#transforms)
|
||||
for the exact details.
|
||||
|
||||
There are some helper functions that simplify creating the ASTs. The above example uses the
|
||||
`transforms_from()` helper function. It is equivalent to:
|
||||
|
||||
```python
|
||||
ctx.add_transforms(
|
||||
"calendar/calendar/calendar-widgets.ftl",
|
||||
"calendar/calendar/calendar-widgets.ftl",
|
||||
[
|
||||
FTL.Message(
|
||||
id=FTL.Identifier("calendar-view-toggle-day"),
|
||||
value=COPY("calendar/chrome/calendar/calendar.dtd", "calendar.day.button.label"),
|
||||
attributes=[
|
||||
FTL.Attribute(
|
||||
id=FTL.Identifier("title"),
|
||||
value=COPY(
|
||||
"calendar/chrome/calendar/calendar.dtd",
|
||||
"calendar.day.button.tooltip"
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
`transforms_from()` allows copying reference FTL strings, and replacing the value
|
||||
of each message with a `COPY` Transform that copies values from the DTD file at
|
||||
`from_path`.
|
||||
|
||||
There are other Transforms like `COPY`. See
|
||||
[Migrating Legacy Formats](https://firefox-source-docs.mozilla.org/l10n/migrations/legacy.html)
|
||||
for usage information.
|
|
@ -0,0 +1,16 @@
|
|||
# Localization
|
||||
|
||||
At Mozilla, localization refers to adapting the user interface and messages
|
||||
to different cultural and regional needs. Localization is a broader term than
|
||||
translation because it involves extensive research into the target culture, and
|
||||
in result touches not only text and UI translation but also cultural adaptation
|
||||
of icons, communication styles, colors, and UX.
|
||||
|
||||
Questions about Thunderbird localization should be directed to the Localization
|
||||
Coordinator. Contact information is on the
|
||||
[Thunderbird Project page in Pontoon](https://pontoon.mozilla.org/projects/thunderbird/info/).
|
||||
|
||||
```{toctree}
|
||||
fluent_migrations
|
||||
testing_migrations
|
||||
```
|
|
@ -0,0 +1,39 @@
|
|||
# Testing Migration Recipes
|
||||
|
||||
## During Development
|
||||
|
||||
To test migration recipes during development, use the following mach command:
|
||||
|
||||
```bash
|
||||
./mach tb-fluent-migration-test comm/python/l10n/tb_fluent_migrations/bug_1805746_calendar_view.py
|
||||
```
|
||||
|
||||
This will analyze your migration recipe to check that the migrate function exists,
|
||||
and interacts correctly with the migration context. Once that passes, it clones
|
||||
`comm-strings-quarantine` into `$OBJDIR/comm/python/l10n`, creates a reference
|
||||
localization by adding your local Fluent strings to the ones in
|
||||
`comm-strings-quarantine` (essentially the first part of the cross-channel
|
||||
process).
|
||||
|
||||
It then runs the migration recipe, both as dry run and as actual migration.
|
||||
Finally it analyzes the commits, and checks if any migrations were actually run
|
||||
and the bug number in the commit message matches the migration name.
|
||||
|
||||
It will also show the diff between the migrated files and the reference, ignoring
|
||||
blank lines.
|
||||
|
||||
You can inspect the generated repository further by looking in
|
||||
`$OBJDIR/comm/python/l10n/bug_1805746_calendar_view/en-US`.
|
||||
|
||||
## During Review
|
||||
|
||||
During l10n review, migration scripts will be run against all Thunderbird locales.
|
||||
Any problems will be reported back to the author as part of the regular code
|
||||
review process in Phabricator.
|
||||
|
||||
```{tip}
|
||||
Plan on extra review time for migration scripts in case changes are needed.
|
||||
|
||||
Ask the Thunderbird L10n coordinator in [#maildev](https://matrix.to/#/#maildev:mozilla.org)
|
||||
or your manager if you run into problems.
|
||||
```
|
|
@ -1,35 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
|
@ -1,3 +1,4 @@
|
|||
Sphinx>=5,<6
|
||||
sphinx_rtd_theme
|
||||
myst-parser[linkify]
|
||||
fluent.pygments>=1,<2
|
||||
|
|
|
@ -2,21 +2,25 @@
|
|||
# This file is autogenerated by pip-compile with Python 3.10
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile requirements.in
|
||||
# pip-compile --resolver=backtracking requirements.in
|
||||
#
|
||||
alabaster==0.7.12
|
||||
alabaster==0.7.13
|
||||
# via sphinx
|
||||
babel==2.11.0
|
||||
# via sphinx
|
||||
certifi==2022.12.7
|
||||
# via requests
|
||||
charset-normalizer==2.1.1
|
||||
charset-normalizer==3.0.1
|
||||
# via requests
|
||||
docutils==0.17.1
|
||||
# via
|
||||
# myst-parser
|
||||
# sphinx
|
||||
# sphinx-rtd-theme
|
||||
fluent-pygments==1.0
|
||||
# via -r requirements.in
|
||||
fluent-syntax==0.18.1
|
||||
# via fluent-pygments
|
||||
idna==3.4
|
||||
# via requests
|
||||
imagesize==1.4.1
|
||||
|
@ -39,16 +43,20 @@ mdurl==0.1.2
|
|||
# via markdown-it-py
|
||||
myst-parser[linkify]==0.18.1
|
||||
# via -r requirements.in
|
||||
packaging==22.0
|
||||
packaging==23.0
|
||||
# via sphinx
|
||||
pygments==2.13.0
|
||||
# via sphinx
|
||||
pytz==2022.6
|
||||
pygments==2.14.0
|
||||
# via
|
||||
# fluent-pygments
|
||||
# sphinx
|
||||
pytz==2022.7
|
||||
# via babel
|
||||
pyyaml==6.0
|
||||
# via myst-parser
|
||||
requests==2.28.1
|
||||
requests==2.28.2
|
||||
# via sphinx
|
||||
six==1.16.0
|
||||
# via fluent-pygments
|
||||
snowballstemmer==2.2.0
|
||||
# via sphinx
|
||||
sphinx==5.3.0
|
||||
|
@ -58,7 +66,7 @@ sphinx==5.3.0
|
|||
# sphinx-rtd-theme
|
||||
sphinx-rtd-theme==1.1.1
|
||||
# via -r requirements.in
|
||||
sphinxcontrib-applehelp==1.0.2
|
||||
sphinxcontrib-applehelp==1.0.3
|
||||
# via sphinx
|
||||
sphinxcontrib-devhelp==1.0.2
|
||||
# via sphinx
|
||||
|
@ -74,5 +82,5 @@ typing-extensions==4.4.0
|
|||
# via myst-parser
|
||||
uc-micro-py==1.0.1
|
||||
# via linkify-it-py
|
||||
urllib3==1.26.13
|
||||
urllib3==1.26.14
|
||||
# via requests
|
||||
|
|
|
@ -9,11 +9,9 @@ var EXPORTED_SYMBOLS = ["PromptParent"];
|
|||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
lazy,
|
||||
"PromptUtils",
|
||||
"resource://gre/modules/SharedPromptUtils.jsm"
|
||||
);
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
PromptUtils: "resource://gre/modules/PromptUtils.sys.mjs",
|
||||
});
|
||||
|
||||
/**
|
||||
* @typedef {object} Prompt
|
||||
|
|
|
@ -188,8 +188,8 @@ var gBigFileObserver = {
|
|||
} else if (accounts.length > 1) {
|
||||
// We once used Services.prompt.select for this UI, but it doesn't support displaying an
|
||||
// icon for each item. The following code does the same thing with a replacement dialog.
|
||||
let { PromptUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/SharedPromptUtils.jsm"
|
||||
let { PromptUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/PromptUtils.sys.mjs"
|
||||
);
|
||||
|
||||
let names = accounts.map(i => cloudFileAccounts.getDisplayName(i));
|
||||
|
|
|
@ -1 +1 @@
|
|||
110.0a1
|
||||
111.0a1
|
||||
|
|
|
@ -1 +1 @@
|
|||
110.0a1
|
||||
111.0a1
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
|
||||
var EXPORTED_SYMBOLS = ["MsgAsyncPrompter", "MsgAuthPrompt"];
|
||||
|
||||
var { Deprecated } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/Deprecated.sys.mjs"
|
||||
);
|
||||
const { PromptUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/SharedPromptUtils.jsm"
|
||||
);
|
||||
var { XPCOMUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/XPCOMUtils.sys.mjs"
|
||||
);
|
||||
|
@ -22,6 +16,11 @@ const LoginInfo = Components.Constructor(
|
|||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
Deprecated: "resource://gre/modules/Deprecated.sys.mjs",
|
||||
PromptUtils: "resource://gre/modules/PromptUtils.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(lazy, "dialogsBundle", function() {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://global/locale/commonDialogs.properties"
|
||||
|
@ -56,7 +55,7 @@ runnablePrompter.prototype = {
|
|||
} catch (e) {
|
||||
if (e.result == Cr.NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
|
||||
// Fall back to onPromptStart, for add-ons compat
|
||||
Deprecated.warning(
|
||||
lazy.Deprecated.warning(
|
||||
"onPromptStart has been replaced by onPromptStartAsync",
|
||||
"https://bugzilla.mozilla.org/show_bug.cgi?id=1176399"
|
||||
);
|
||||
|
@ -551,7 +550,7 @@ function nsIPrompt_promptUsernameAndPassword(
|
|||
ok: false,
|
||||
};
|
||||
|
||||
let propBag = PromptUtils.objectToPropBag(args);
|
||||
let propBag = lazy.PromptUtils.objectToPropBag(args);
|
||||
Services.ww.openWindow(
|
||||
Services.ww.activeWindow,
|
||||
"chrome://global/content/commonDialog.xhtml",
|
||||
|
@ -559,7 +558,7 @@ function nsIPrompt_promptUsernameAndPassword(
|
|||
"centerscreen,chrome,modal,titlebar",
|
||||
propBag
|
||||
);
|
||||
PromptUtils.propBagToObject(propBag, args);
|
||||
lazy.PromptUtils.propBagToObject(propBag, args);
|
||||
|
||||
// Did user click Ok or Cancel?
|
||||
let ok = args.ok;
|
||||
|
@ -619,7 +618,7 @@ function nsIPrompt_promptPassword(
|
|||
ok: false,
|
||||
};
|
||||
|
||||
let propBag = PromptUtils.objectToPropBag(args);
|
||||
let propBag = lazy.PromptUtils.objectToPropBag(args);
|
||||
Services.ww.openWindow(
|
||||
Services.ww.activeWindow,
|
||||
"chrome://global/content/commonDialog.xhtml",
|
||||
|
@ -627,7 +626,7 @@ function nsIPrompt_promptPassword(
|
|||
"centerscreen,chrome,modal,titlebar",
|
||||
propBag
|
||||
);
|
||||
PromptUtils.propBagToObject(propBag, args);
|
||||
lazy.PromptUtils.propBagToObject(propBag, args);
|
||||
|
||||
// Did user click Ok or Cancel?
|
||||
let ok = args.ok;
|
||||
|
|
|
@ -18,10 +18,7 @@ class nsMessengerWinIntegration : public nsIMessengerWindowsIntegration {
|
|||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMESSENGERWINDOWSINTEGRATION
|
||||
|
||||
NS_IMETHOD UpdateUnreadCount(uint32_t unreadCount,
|
||||
const nsAString& unreadTooltip);
|
||||
NS_IMETHOD OnExit();
|
||||
NS_DECL_NSIMESSENGEROSINTEGRATION
|
||||
|
||||
private:
|
||||
static LRESULT CALLBACK IconWindowProc(HWND msgWindow, UINT msg, WPARAM wp,
|
||||
|
|
|
@ -1718,22 +1718,6 @@ nsMsgLocalMailFolder::CopyFileMessage(nsIFile* aFile, nsIMsgDBHdr* msgToReplace,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMsgLocalMailFolder::DeleteMessage(nsISupports* message,
|
||||
nsIMsgWindow* msgWindow,
|
||||
bool deleteStorage, bool commit) {
|
||||
nsresult rv = NS_OK;
|
||||
if (deleteStorage) {
|
||||
nsCOMPtr<nsIMsgDBHdr> msgDBHdr(do_QueryInterface(message, &rv));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
GetDatabase();
|
||||
if (mDatabase)
|
||||
rv = mDatabase->DeleteHeader(msgDBHdr, nullptr, commit, true);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgLocalMailFolder::GetNewMessages(nsIMsgWindow* aWindow,
|
||||
nsIUrlListener* aListener) {
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
|
|
|
@ -215,8 +215,6 @@ class nsMsgLocalMailFolder : public nsMsgDBFolder,
|
|||
nsresult ConfirmFolderDeletion(nsIMsgWindow* aMsgWindow,
|
||||
nsIMsgFolder* aFolder, bool* aResult);
|
||||
|
||||
nsresult DeleteMessage(nsISupports* message, nsIMsgWindow* msgWindow,
|
||||
bool deleteStorage, bool commit);
|
||||
nsresult GetDatabase() override;
|
||||
// this will set mDatabase, if successful. It will also create a .msf file
|
||||
// for an empty local mail folder. It will leave invalid DBs in place, and
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.107a1
|
||||
2.108a1
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.107a1
|
||||
2.108a1
|
||||
|
|
Загрузка…
Ссылка в новой задаче