* Remove `plans2026` from pug files in subscriptions module
* Remove `plans2026` param from `makeGroupPlans`
* Remove `plans2026` param from `makeUISettings` in interstitial-payment.mjs
* Remove `plans2026` param from `makeInterstitialPaymentConfig` in interstitial-payment.mjs
* Remove `plans2026` param from `makeIndividualPlans`
* Remove `plans2026` param from `makeStudentPlans`
* Remove `plans2026` from try-premium page
* Remove `plans2026` from controllers
* Remove unused files
* Update translations
* Update tests
* Update tests
* Remove unused translations
* Rename the collaborator upgrade-mode test to read explicitly as the
Standard-plan replacement for the removed redirect test, and drop the
stale "when plans 2026 is enabled" framing now the controller no longer
branches on the flag.
* Surface controller errors in InterstitialPayment tests
Move assertions out of the res.render callback into render/redirect
helpers that resolve with the captured args and reject on the wrong
path or a controller rejection, so failures show the real error
instead of timing out. Restore the ai-limit-upgrade-copy split-test
assignment for the AI copy tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* format
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
GitOrigin-RevId: f0b055b4d92b494b531766a13b057336d9c2c9af
* Hide tax note when tax is included and update zero-tax disclaimer wording
* fix: update taxes_may_be_added key in all non-English locale files
GitOrigin-RevId: 9cd0e0aba6d548221e97d383b0a2e52a2e0a077c
* Remove double spaces
* Enforce curly apostrophes
* Enforce French typographic spaces in fr.json
Add vitest test enforcing French spacing rules per
https://typographisme.net/post/Les-espaces-typographiques-et-le-web:
- NNBSP (U+202F) before ? ! ;
- NBSP (U+00A0) before :
- NBSP (U+00A0) around guillemets « »
Fix 38 fr.json values that were using NBSP (or no space) before ? ! ;.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Extend French typography test to numbers and percent signs
Add rules per https://typographisme.net/post/Les-espaces-typographiques-et-le-web:
- NNBSP (U+202F) between digit groups (thousands separator)
- NBSP (U+00A0) between a number and a following word/unit
- NBSP (U+00A0) before %
Fix 9 fr.json values where a regular space was used instead of NBSP between
a number and a following word (e.g. "1 résultat", "10 jetons", "7 jours").
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Use point médian for inclusive writing in fr.json
Replace parenthetical gender/plural markers like "sûr(e)", "abonné(e)",
"licence(s)" with the point médian "·" (e.g. "sûr·e", "abonné·e",
"licence·s") per modern French écriture inclusive.
Add a vitest rule rejecting "word(suffix)" patterns where suffix is 1-3
letters and there is no space before the opening parenthesis.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Simplify inclusive-writing check to "(e)" substring match
The previous regex (matchAll without the /g flag) would have thrown at
runtime. Drop matchAll entirely and use includes('(e)').
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Add point médian to participles in fr.json
Apply inclusive writing (·e) to past participles agreeing with the
addressed user ("affilié·e", "invité·e", "connecté·e", "abonné·e", etc.).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Use inclusive forms in fr.json
* Change "de Overleaf" to "d’Overleaf"
* Fix tests
* Check for consecutive spaces, not just double spaces
* Update comment about guillemets
* Add ESLint rules for locale JSON conventions
Add three rules to @overleaf/eslint-plugin that run against locale JSON
files via @eslint/json:
- no-consecutive-spaces-in-locales
- no-straight-apostrophes-in-locales
- french-typography-in-locales
Wire them up in services/web/eslint.config.mjs against `locales/*.json`
(and `locales/fr.json` for the French-typography rule).
* Add `@eslint/json` so JSON files can be parsed
* Scope JS/TS-specific config to JS/TS files only so that built-in rules aren't applied to JSON files
* Disable `no-irregular-whitespace` in french-typography-in-locales.js
* Make the rules fixable
* Improve regexes: user `\s` instead of custom matchers
* Add sorted-keys-in-locales ESLint rule
Mirrors scripts/translations/sort.js as a fixable ESLint rule:
require top-level keys in locale JSON files to be sorted alphabetically.
The autofix re-serializes the file with sorted keys.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Add no-unused-locale-keys ESLint rule
Mirrors scripts/translations/cleanupUnusedLocales.js as a fixable ESLint
rule applied only to en.json. Shells out to `find` + `cat` once per
process (cached) to grep all candidate source files for key references,
then reports any en.json key that isn't found. The autofix re-serializes
en.json without the unused keys.
Hardcoded ALWAYS_USED set covers keys built at runtime (month names,
third-party-datastore notifications) that the regex scan can't see.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Add locale-variables-match-en ESLint rule
Mirrors scripts/translations/checkVariables.js as an ESLint rule applied
to non-en locale JSON files. Reads en.json (cached) and reports any
member whose `__name__` placeholders differ from the base.
GLOBALS (e.g. __appName__) are allowed as extras; IGNORE_NESTING_FOR
preserves the script's per-key exceptions.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Replace some double linebreak (@overleaf/no-consecutive-spaces-in-locales)
* Add no-orphan-locale-keys ESLint rule
Detect translation keys in non-en locale files that aren't present in
en.json. Mirrors the `--sync-non-en` flag of cleanupUnusedLocales.js.
The autofix re-serializes the locale file without the orphan keys,
sorted alphabetically.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Add tests for the locale JSON ESLint rules
Cover the four single-file rules:
- no-consecutive-spaces-in-locales
- no-straight-apostrophes-in-locales
- sorted-keys-in-locales
- french-typography-in-locales (including the inclusive-writing
suggestion for "(e)")
The three cross-file rules (no-unused-locale-keys, no-orphan-locale-keys,
locale-variables-match-en) read from disk and aren't covered here; they
need integration tests via fixtures.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Drop bin/lint_locales — checks are now covered by ESLint rules
The four checks in bin/lint_locales are duplicated by the new
@overleaf/eslint-plugin rules:
- sort.js --check → sorted-keys-in-locales
- cleanupUnusedLocales.js --check → no-unused-locale-keys
+ no-orphan-locale-keys
- checkVariables.js → locale-variables-match-en
- single-quote grep → no-straight-apostrophes-in-locales
`yarn lint` runs the ESLint rules against locales/*.json, so the
lint_locales script and Makefile target are redundant.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Remove Locales.test.mjs
* Delete scripts replaced by @overleaf/eslint-plugin rules
Remove the three locale scripts now superseded by ESLint rules:
- scripts/translations/sort.js → sorted-keys-in-locales
- scripts/translations/cleanupUnusedLocales.js → no-unused-locale-keys
+ no-orphan-locale-keys
- scripts/translations/checkVariables.js → locale-variables-match-en
Also drop the matching Makefile targets (sort_locales,
cleanup_unused_locales), update AGENTS.md / copilot-instructions.md to
point at `yarn lint --fix` instead, and prune the deleted entries from
the esm-check-migration allowlist.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Delete redundant scripts/translations/sort-locale-file.js
Single-file sort utility — superseded by `yarn lint --fix path/to/file.json`
via the sorted-keys-in-locales ESLint rule. No callers in repo.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Update comments and messages
* Add test file pattern to ESLint configuration
* Reorder "Backend specific rules" so `no-extraneous-dependencies` doesn't fail on test files
* Make french-typography fixes idempotent and catch edge cases
Apply Copilot's review feedback on PR #34221:
- autoFix() now uses `\\s*`/`\\s+` instead of `\\s?`/`\\s` so it
collapses any run of mixed whitespace into the correct NBSP/NNBSP,
making the fix idempotent and order-independent.
- The `:` lint regex now captures optional whitespace and reports
when it isn't NBSP (catches `"Liste :"` with a regular space).
- The `%` lint regex now matches the missing-space case (`"10%"`)
via `\\s*` instead of requiring one char between digit and `%`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Remove sort-locale-file.js from pre-commit
* Revert no-unused-locale-keys ESLint rule; Restore lint_locales scripts
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
GitOrigin-RevId: 8351fab074e6e7f77920b70237df1cd1c781e053
* Replace token-link email with 6-digit code on SSO registration
Unverified SSO emails previously received a long-lived token link
(90-day TTL) via UserEmailsConfirmationHandler. This replaces that
flow with the same 6-digit code verification used for password
registration, redirecting through /registration/confirm-email.
- SSOManager.registerSSO now always confirms email (caller must
verify first); removes sendConfirmationEmail / _finishRegistration
- SSOController._signUp sends confirmation code and stores
pendingSSORegistration in session when IdP email_verified is false
- New SSOConfirmEmailHandler completes registration after code check
via completeSSOEmailConfirmation module hook
- OnboardingController confirm-email handlers accept
pendingSSORegistration alongside pendingUserRegistration
confirmEmailFromToken (POST /user/emails/confirm) removal is deferred
to a follow-up PR to avoid breaking in-flight 90-day tokens.
Closes#28607
* Fix unverified-email edge cases; Add ORCID e2e tests;
* Rename `confirmEmail` parameter to `emailVerifiedByIdP` in _signUp function
* Remove `sendConfirmationEmail`
* Mock getUserByAnyEmail in tests
* Extract _finishSSORegistration helper to deduplicate the register →
set session flags → allocate referral → finishSaasLogin → finishLogin
sequence shared by both the direct and deferred (code-confirmed) paths.
* Stop duplicating session data in pendingSSORegistration
analyticsId, splitTests, and referal_* are already in the session at
confirmation time — no need to copy them into pendingSSORegistration.
Re-fetch splitTests fresh on completion instead.
* Simplify the code
* Remove dead confirmEmail template
No callers remain after sendConfirmationEmail was deleted. The token-link
flow (confirmEmailFromToken) only validates tokens, never sends email.
* Remove dead reconfirmEmail template
* Address comments from Copilot
* Clear stale pending registration when starting a new flow
* Add unit tests for completeSSOEmailConfirmation
* Add `verificationMethod` param
* Fix camelcase issues
* Extract _createSSOUser and _registerAndFinish helpers to deduplicate registration logic
* Remove obscure "registration_error"
* Prevent FormTextIcon from shrinking
* Enable "email_already_registered_sso" error
* Misc. improvements to confirm-email-form.tsx
* Remove `UserEmailsConfirmationHandler` mock
Co-authored-by: Olzhas Askar <olzhas.askar@overleaf.com>
* Add info on sso_email.pug page
---------
Co-authored-by: Olzhas Askar <olzhas.askar@overleaf.com>
GitOrigin-RevId: d0196ebc6d81ff61bcd27726d0b899b743d08d64
* Add tests on plurals
* Update `collabs_per_proj` and its pluralisations
* Update `n_user` and its pluralisations
* Update `showing_x_results` and its pluralisations
* Update `show_x_more_projects` and its pluralisations
* `bin/run web npm run extract-translations`
* Populate `_plural` keys in non-en locales
For 2-form languages (da, de, es, fi, fr, it, nl, no, pt, sv, tr), copy
the existing bare-key value into the new `_plural` sibling to prevent
i18next from falling back to English for count!=1.
Also remove orphan singular keys (`collabs_per_proj_single`,
`showing_1_result*`) left over from the previous commits.
Bare-key values remain in their original plural form pending translator
review — count=1 will still render the plural form in non-en until
translators flip those to singular. Multi-form (cs, pl, ru) and
single-form (ja, ko, zh-CN, zh-TW) locales are unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Flip non-en bare-key values to singular form
Per review, the i18next v3 plural convention uses the bare key for count=1
(singular) and `_plural` for count!=1. The non-en bare-key values were
left as the original plural form by the previous commit so the `_plural`
siblings could be copied from them; this commit flips the bare values to
the singular form per language.
Languages where singular and plural noun forms coincide (Finnish, Swedish,
Turkish) are unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Apply suggestions from code review
Co-authored-by: Olzhas Askar <olzhas.askar@gmail.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Olzhas Askar <olzhas.askar@gmail.com>
GitOrigin-RevId: 628513ca792c2dcce023247e52b7320e2741cc54
* [web] Replace `pro` with `commons` wording on institutional subscriptions
Replaces the wording in several places:
- subscription settings
- email tags
- features tooltip
- institution portal
GitOrigin-RevId: 1b9a0e51245ed8a41865300d9e9d555bc05e6c17
* Change the refund policy from 30 to 14 days
* Align AI suggestions trial period with 14-day refund policy
* Revert "Align AI suggestions trial period with 14-day refund policy"
This reverts commit d3327c71c05543a751acd66450183bbf0eb95fd7.
GitOrigin-RevId: b77e09b2bb508951b68ae3a00b95146e6898bac5
* no grey hyphen when the input is empty
* show email in bold
* Fix tests
* Add test to verify email display in confirmation code input
* Format
GitOrigin-RevId: ade4a670b9dc80b99f64cc3273407a98428521b8
* adding plural translations for the languages that were easy to test with the help of AI
* adding remaining translations
* adding your_subscriptions
* running make sort_locales
* fixing nl.json to make it formal You
GitOrigin-RevId: 7510e2f8eee87fd2a256ece434cc59e6877893e6
* Conditionally render a CIAM copy of login.pug depending on `ciam` split-test
* Conditionally render a CIAM copy of register.pug depending on `ciam` split-test
* Conditionally render a CIAM copy of institutional_login.pug depending on `ciam` split-test
* Rename the test to `uniaccessphase1`
* Fixup ciam paths (underscores, not hyphens)
* Escape translations in `log_in_with_existing_institution_email`
See https://github.com/overleaf/internal/pull/29390#discussion_r2479318609
GitOrigin-RevId: fff0e154d1e1faad4842a2c49fa5889f9cc189e6
* Temporarily update `maxEntitiesPerProject` to test `FileTreeModalCreateFile`
* Remove unused CSS
* Move project_has_too_many_files Notification to the modal body
* Turn project_approaching_file_limit message into a Notification
* Update project_has_too_many_files translation with `fileCount.limit`
* Update other project_has_too_many_files with limit parameter
* Add translations for project_has_too_many_files_limit
* Revert "Temporarily update `maxEntitiesPerProject` to test `FileTreeModalCreateFile`"
This reverts commit 704996aa96c9ba592c7e44d165def0b97d30bed1.
* Fix unit tests
* Move the warning notification to the modal's body
---------
Co-authored-by: Rebeka <o.dekany@gmail.com>
GitOrigin-RevId: 0f54db7021e4cd4537a14e4f9e1d8ef54337778c