mirror of
https://github.com/fluxerapp/fluxer.git
synced 2026-09-02 21:04:06 +03:00
ci: add tests (#1141)
This commit is contained in:
@@ -43,7 +43,6 @@ defaults:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_OWNER: ${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -23,7 +23,6 @@ permissions:
|
||||
packages: write
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_OWNER: ${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -37,7 +37,6 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
CHANNEL: ${{ inputs.channel }}
|
||||
BUILD_CHANNEL: ${{ inputs.channel == 'canary' && 'canary' || 'stable' }}
|
||||
TEST_BUILD: ${{ inputs.test_build && 'true' || 'false' }}
|
||||
|
||||
@@ -80,7 +80,6 @@ on:
|
||||
required: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_OWNER: ${{ github.repository_owner }}
|
||||
GHCR_REGISTRY: ghcr.io/${{ github.repository_owner }}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ defaults:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
SOURCE_BRANCH: automation/i18n-source-catalogs
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ defaults:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
WEBLATE_BRANCH: ${{ github.event.inputs.branch || github.ref_name }}
|
||||
|
||||
|
||||
@@ -10,9 +10,6 @@ on:
|
||||
required: false
|
||||
default: "assets/"
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
repair:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
@@ -4,9 +4,6 @@ name: sync static bucket
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
push:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
name: CI
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
GHCR_REGISTRY: ghcr.io/${{ github.repository_owner }}
|
||||
|
||||
jobs:
|
||||
@@ -20,6 +26,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
targets: wasm32-unknown-unknown
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
@@ -51,6 +58,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
targets: wasm32-unknown-unknown
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
@@ -84,6 +92,15 @@ jobs:
|
||||
toolchain: stable
|
||||
components: clippy, rustfmt
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
|
||||
with:
|
||||
@@ -95,6 +112,21 @@ jobs:
|
||||
restore-keys: |
|
||||
rust-${{ runner.os }}-
|
||||
|
||||
- name: Install native dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
pkg-config \
|
||||
build-essential \
|
||||
libcurl4-openssl-dev \
|
||||
libvips-dev \
|
||||
libavfilter-dev \
|
||||
libheif-dev \
|
||||
libwebp-dev
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: pnpm --filter fluxer_admin --filter fluxer_marketing install
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
@@ -104,33 +136,6 @@ jobs:
|
||||
- name: Run tests
|
||||
run: cargo test --workspace
|
||||
|
||||
marketing-docker:
|
||||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
||||
|
||||
- name: Set up Rust toolchain (CI helpers)
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f
|
||||
|
||||
- name: Build marketing image
|
||||
run: |
|
||||
BUILD_VERSION="$(cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- resolve-calver)"
|
||||
docker build \
|
||||
-f fluxer_marketing/Dockerfile \
|
||||
-t "fluxer-marketing:${BUILD_VERSION}" \
|
||||
--build-arg "BUILD_VERSION=${BUILD_VERSION}" \
|
||||
.
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
gateway:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 25
|
||||
@@ -190,6 +195,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
|
||||
with:
|
||||
toolchain: "1.93.0"
|
||||
targets: wasm32-unknown-unknown
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@c5ba7f7862a0f64c1b1a05fbac13e0b8e86ba08c
|
||||
@@ -291,6 +297,9 @@ jobs:
|
||||
*marketing*)
|
||||
EXTRA_SETS+=(--set-string app.name=marketing --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*docs*)
|
||||
EXTRA_SETS+=(--set-string app.name=docs --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
*media-proxy*)
|
||||
EXTRA_SETS+=(--set-string "mediaProxy.tag=${HELM_TEST_BUILD_VERSION}" --set-string "staticProxy.tag=${HELM_TEST_BUILD_VERSION}" --set-string "mediaProxy.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "staticProxy.build.version=${HELM_TEST_BUILD_VERSION}")
|
||||
;;
|
||||
@@ -178,7 +178,7 @@ pub struct InstanceMediaResponse {
|
||||
pub attachment_decay: InstanceAttachmentDecayResponse,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct InstanceAttachmentDecayResponse {
|
||||
pub enabled: Option<bool>,
|
||||
pub min_size_mb: Option<f64>,
|
||||
@@ -193,23 +193,6 @@ pub struct InstanceAttachmentDecayResponse {
|
||||
pub effective: InstanceAttachmentDecayEffectiveResponse,
|
||||
}
|
||||
|
||||
impl Default for InstanceAttachmentDecayResponse {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: None,
|
||||
min_size_mb: None,
|
||||
max_size_mb: None,
|
||||
max_eligible_size_mb: None,
|
||||
min_lifetime_days: None,
|
||||
max_lifetime_days: None,
|
||||
curve: None,
|
||||
renew_threshold_days: None,
|
||||
renew_window_days: None,
|
||||
effective: InstanceAttachmentDecayEffectiveResponse::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct InstanceAttachmentDecayEffectiveResponse {
|
||||
#[serde(default)]
|
||||
@@ -297,7 +280,7 @@ impl PremiumMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct AppPublicConfigResponse {
|
||||
#[serde(default)]
|
||||
pub branding: AppBrandingConfigResponse,
|
||||
@@ -309,17 +292,6 @@ pub struct AppPublicConfigResponse {
|
||||
pub registration: AppRegistrationConfigResponse,
|
||||
}
|
||||
|
||||
impl Default for AppPublicConfigResponse {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
branding: AppBrandingConfigResponse::default(),
|
||||
setup: AppSetupConfigResponse::default(),
|
||||
legal: AppLegalConfigResponse::default(),
|
||||
registration: AppRegistrationConfigResponse::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct AppBrandingConfigResponse {
|
||||
#[serde(default = "default_product_name")]
|
||||
|
||||
Vendored
+1
-5
@@ -7,8 +7,6 @@
|
||||
"./*": "./*"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"typecheck": "tsgo --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -16,8 +14,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "catalog:",
|
||||
"@typescript/native-preview": "catalog:",
|
||||
"vite-tsconfig-paths": "catalog:",
|
||||
"vitest": "catalog:"
|
||||
"@typescript/native-preview": "catalog:"
|
||||
}
|
||||
}
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import path from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import {defineConfig} from 'vitest/config';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
tsconfigPaths({
|
||||
root: path.resolve(__dirname, '../..'),
|
||||
}),
|
||||
],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: ['**/*.{test,spec}.{ts,tsx}'],
|
||||
exclude: ['node_modules', 'dist'],
|
||||
coverage: {
|
||||
provider: 'v8',
|
||||
reporter: ['text', 'json', 'html'],
|
||||
exclude: ['**/*.test.tsx', '**/*.spec.tsx', 'node_modules/'],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -48,10 +48,6 @@ export function getEmailTemplate(
|
||||
return emailI18n.getTemplate(templateKey, locale, {...DEFAULT_EMAIL_TEMPLATE_VARIABLES, ...variables});
|
||||
}
|
||||
|
||||
export function hasEmailLocale(locale: string): boolean {
|
||||
return emailI18n.hasLocale(locale);
|
||||
}
|
||||
|
||||
export function resetEmailI18n(): void {
|
||||
emailI18n.reset();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_AR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_AR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "تم تعطيل حسابك في {product_name} مؤقتًا",
|
||||
"body": "مرحباً {username}،\n\nلقد قمنا بتعطيل حسابك في {product_name} مؤقتًا لأننا اكتشفنا نشاطًا مشبوهًا.\n\n{reason, select,\n null {}\n other {السبب: {reason}}\n}\n\nلاستعادة الوصول إلى حسابك، ستحتاج إلى إعادة تعيين كلمة المرور الخاصة بك:\n\n{forgotUrl}\n\nبعد إعادة تعيين كلمة المرور الخاصة بك، ستتمكن من تسجيل الدخول مرة أخرى.\n\nإذا كنت تعتقد أن هذا حدث عن طريق الخطأ، يرجى الاتصال بفريق الدعم لدينا.\n\n– فريق أمان {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_BG_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_BG_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Акаунтът ти във {product_name} е временно деактивиран",
|
||||
"body": "Здравей, {username},\n\nВременно деактивирахме акаунта ти във {product_name}, защото открихме подозрителна активност.\n\n{reason, select,\n null {}\n other {Причина: {reason}}\n}\n\nЗа да възстановиш достъпа до акаунта си, трябва да нулираш паролата си:\n\n{forgotUrl}\n\nСлед като нулираш паролата си, ще можеш да влезеш отново.\n\nАко смяташ, че това е грешка, свържи се с нашия екип за поддръжка.\n\n– Екип за безопасност на {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_CS_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_CS_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Tvůj účet {product_name} byl dočasně deaktivován",
|
||||
"body": "Ahoj {username},\n\nDočasně jsme deaktivovali tvůj účet {product_name}, protože jsme zaznamenali podezřelou aktivitu.\n\n{reason, select,\n null {}\n other {Důvod: {reason}}\n}\n\nPro opětovný přístup k účtu si budeš muset resetovat heslo:\n\n{forgotUrl}\n\nPo resetování hesla se budeš moci znovu přihlásit.\n\nPokud se domníváš, že se jedná o chybu, kontaktuj prosím náš tým podpory.\n\n– Bezpečnostní tým {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_DA_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_DA_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Din {product_name}-konto er midlertidigt deaktiveret",
|
||||
"body": "Hej {username},\n\nVi har midlertidigt deaktiveret din {product_name}-konto, fordi vi har registreret mistænkelig aktivitet.\n\n{reason, select,\n null {}\n other {Årsag: {reason}}\n}\n\nFor at få adgang til din konto igen skal du nulstille din adgangskode:\n\n{forgotUrl}\n\nNår du har nulstillet din adgangskode, kan du logge ind igen.\n\nHvis du mener, at dette er sket ved en fejl, kan du kontakte vores supportteam.\n\n– {product_name} Safety Team"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_DE_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_DE_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Dein {product_name}-Konto wurde vorübergehend deaktiviert",
|
||||
"body": "Hallo {username},\n\nwir haben dein {product_name}-Konto vorübergehend deaktiviert, da wir verdächtige Aktivitäten festgestellt haben.\n\n{reason, select,\n null {}\n other {Grund: {reason}}\n}\n\nUm wieder Zugriff auf dein Konto zu erhalten, musst du dein Passwort zurücksetzen:\n\n{forgotUrl}\n\nNachdem du dein Passwort zurückgesetzt hast, kannst du dich wieder anmelden.\n\nWenn du glaubst, dass dies ein Fehler war, kontaktiere bitte unser Support-Team.\n\n– {product_name}-Sicherheitsteam"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_EL_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_EL_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Ο λογαριασμός σου στο {product_name} έχει απενεργοποιηθεί προσωρινά",
|
||||
"body": "Γεια σου {username},\n\nΑπενεργοποιήσαμε προσωρινά τον λογαριασμό σου στο {product_name} επειδή εντοπίσαμε ύποπτη δραστηριότητα.\n\n{reason, select,\n null {}\n other {Λόγος: {reason}}\n}\n\nΓια να αποκτήσεις ξανά πρόσβαση στον λογαριασμό σου, θα πρέπει να επαναφέρεις τον κωδικό πρόσβασής σου:\n\n{forgotUrl}\n\nΑφού επαναφέρεις τον κωδικό πρόσβασής σου, θα μπορείς να συνδεθείς ξανά.\n\nΕάν πιστεύεις ότι αυτό έγινε κατά λάθος, επικοινώνησε με την ομάδα υποστήριξής μας.\n\n– Ομάδα Ασφαλείας {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_EN_GB_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_EN_GB_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Your {product_name} account has been temporarily disabled",
|
||||
"body": "Hello {username},\n\nWe temporarily disabled your {product_name} account because we detected suspicious activity.\n\n{reason, select,\n null {}\n other {Reason: {reason}}\n}\n\nTo regain access to your account, you'll need to reset your password:\n\n{forgotUrl}\n\nAfter you reset your password, you'll be able to log in again.\n\nIf you believe this was done in error, please contact our support team.\n\n– {product_name} Safety Team"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_ES_419_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_ES_419_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Tu cuenta de {product_name} ha sido deshabilitada temporalmente",
|
||||
"body": "Hola {username}:\n\nDeshabilitamos temporalmente tu cuenta de {product_name} porque detectamos actividad sospechosa.\n\n{reason, select,\n null {}\n other {Motivo: {reason}}\n}\n\nPara recuperar el acceso a tu cuenta, deberás restablecer tu contraseña:\n\n{forgotUrl}\n\nDespués de restablecer tu contraseña, podrás iniciar sesión de nuevo.\n\nSi crees que esto fue un error, comunícate con nuestro equipo de soporte.\n\n– Equipo de Seguridad de {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_ES_ES_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_ES_ES_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Tu cuenta de {product_name} ha sido deshabilitada temporalmente",
|
||||
"body": "Hola {username}:\n\nHemos deshabilitado temporalmente tu cuenta de {product_name} porque hemos detectado actividad sospechosa.\n\n{reason, select,\n null {}\n other {Motivo: {reason}}\n}\n\nPara recuperar el acceso a tu cuenta, tendrás que restablecer tu contraseña:\n\n{forgotUrl}\n\nDespués de restablecer tu contraseña, podrás iniciar sesión de nuevo.\n\nSi crees que esto ha sido un error, ponte en contacto con nuestro equipo de soporte.\n\n– Equipo de Seguridad de {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_FI_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_FI_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Käyttäjätilisi {product_name}-palvelussa on tilapäisesti poistettu käytöstä",
|
||||
"body": "Hei {username},\n\nOlemme poistaneet {product_name}-tilisi tilapäisesti käytöstä, koska havaitsimme epäilyttävää toimintaa.\n\n{reason, select,\n null {}\n other {Syy: {reason}}\n}\n\nPäästäksesi takaisin tilillesi sinun on nollattava salasanasi:\n\n{forgotUrl}\n\nKun olet nollannut salasanasi, voit kirjautua sisään uudelleen.\n\nJos uskot, että tämä oli virhe, ota yhteyttä tukitiimiimme.\n\n– {product_name}-turvallisuustiimi"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_FR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_FR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Ton compte {product_name} a été temporairement désactivé",
|
||||
"body": "Bonjour {username},\n\nNous avons temporairement désactivé ton compte {product_name} car nous avons détecté une activité suspecte.\n\n{reason, select,\n null {}\n other {Raison : {reason}}\n}\n\nPour retrouver l'accès à ton compte, tu devras réinitialiser ton mot de passe :\n\n{forgotUrl}\n\nAprès avoir réinitialisé ton mot de passe, tu pourras te connecter à nouveau.\n\nSi tu penses qu'il s'agit d'une erreur, contacte notre équipe d'assistance.\n\n– Équipe de sécurité de {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_HE_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_HE_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "חשבון ה-{product_name} שלך הושבת זמנית",
|
||||
"body": "שלום {username},\n\nחשבון ה-{product_name} שלך הושבת זמנית עקב זיהוי פעילות חשודה.\n\n{reason, select,\n null {}\n other {סיבה: {reason}}\n}\n\nכדי לקבל בחזרה גישה לחשבון, יש לאפס את הסיסמה:\n\n{forgotUrl}\n\nלאחר איפוס הסיסמה, ניתן יהיה להתחבר שוב.\n\nאם אתם חושבים שזו טעות, צרו קשר עם צוות התמיכה שלנו.\n\nצוות הבטיחות של {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_HI_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_HI_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "आपका {product_name} अकाउंट अस्थायी रूप से डिसेबल कर दिया गया है",
|
||||
"body": "नमस्ते {username},\n\nहमने आपके {product_name} अकाउंट को अस्थायी रूप से डिसेबल कर दिया है क्योंकि हमें संदिग्ध एक्टिविटी देखी गई है।\n\n{reason, select,\n null {}\n other {वजह: {reason}}\n}\n\nअपने अकाउंट का एक्सेस फिर से पाने के लिए, आपको अपना पासवर्ड रीसेट करना होगा:\n\n{forgotUrl}\n\nअपना पासवर्ड रीसेट करने के बाद, आप फिर से लॉगिन कर पाएंगे।\n\nअगर आपको लगता है कि यह गलती से हुआ है, तो कृपया हमारी सपोर्ट टीम से संपर्क करें।\n\n– {product_name} सेफ्टी टीम"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_HR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_HR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Tvoj {product_name} račun je privremeno onemogućen",
|
||||
"body": "Pozdrav {username},\n\nPrivremeno smo onemogućili tvoj {product_name} račun jer smo otkrili sumnjivu aktivnost.\n\n{reason, select,\n null {}\n other {Razlog: {reason}}\n}\n\nDa bi ponovno pristupio svom računu, morat ćeš poništiti lozinku:\n\n{forgotUrl}\n\nNakon što poništiš lozinku, moći ćeš se ponovno prijaviti.\n\nAko misliš da je ovo pogreška, kontaktiraj naš tim za podršku.\n\n– {product_name} Sigurnosni Tim"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_HU_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_HU_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "A {product_name} fiókodat ideiglenesen letiltottuk",
|
||||
"body": "Szia {username},\n\nIdeiglenesen letiltottuk a {product_name} fiókodat, mert gyanús tevékenységet észleltünk.\n\n{reason, select,\n null {}\n other {Indok: {reason}}\n}\n\nA fiókodhoz való hozzáférés visszaszerzéséhez vissza kell állítanod a jelszavadat:\n\n{forgotUrl}\n\nA jelszó visszaállítása után újra be tudsz jelentkezni.\n\nHa úgy gondolod, hogy ez tévedésből történt, vedd fel a kapcsolatot a támogatási csapatunkkal.\n\n– {product_name} Biztonsági Csapat"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_ID_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_ID_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Akun {product_name}mu telah dinonaktifkan sementara",
|
||||
"body": "Halo {username},\n\nKami menonaktifkan sementara akun {product_name}mu karena kami mendeteksi aktivitas mencurigakan.\n\n{reason, select,\n null {}\n other {Alasan: {reason}}\n}\n\nUntuk mendapatkan kembali akses ke akunmu, kamu perlu mengatur ulang kata sandimu:\n\n{forgotUrl}\n\nSetelah kamu mengatur ulang kata sandimu, kamu akan bisa masuk lagi.\n\nKalau kamu merasa ini salah, hubungi tim dukungan kami.\n\n– Tim Keamanan {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_IT_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_IT_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Il tuo account {product_name} è stato temporaneamente disabilitato",
|
||||
"body": "Ciao {username},\n\nAbbiamo temporaneamente disabilitato il tuo account {product_name} perché abbiamo rilevato attività sospette.\n\n{reason, select,\n null {}\n other {Motivo: {reason}}\n}\n\nPer riottenere l'accesso al tuo account, dovrai reimpostare la password:\n\n{forgotUrl}\n\nDopo aver reimpostato la password, potrai accedere di nuovo.\n\nSe ritieni che ciò sia stato fatto per errore, contatta il nostro team di supporto.\n\n– Team di Sicurezza {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_JA_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_JA_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "{product_name}アカウントが一時的に無効になりました",
|
||||
"body": "こんにちは、{username}さん\n\n不審なアクティビティが検出されたため、{product_name}アカウントを一時的に無効にしました。\n\n{reason, select,\n null {}\n other {理由: {reason}}\n}\n\nアカウントに再度アクセスするには、パスワードをリセットする必要があります。\n\n{forgotUrl}\n\nパスワードをリセットすると、再度ログインできるようになります。\n\nこの措置が誤りであると思われる場合は、サポートチームにお問い合わせください。\n\n– {product_name}安全チーム"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_KO_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_KO_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "{product_name} 계정이 일시적으로 비활성화되었어요",
|
||||
"body": "안녕하세요, {username}님.\n\n의심스러운 활동이 감지되어 {product_name} 계정을 일시적으로 비활성화했어요.\n\n{reason, select,\n null {}\n other {사유: {reason}}\n}\n\n계정에 다시 액세스하려면 비밀번호를 재설정해야 해요:\n\n{forgotUrl}\n\n비밀번호를 재설정한 후 다시 로그인할 수 있어요.\n\n실수로 비활성화되었다고 생각되면 고객지원팀에 문의해 주세요.\n\n– {product_name} 안전팀"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_LT_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_LT_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Tavo {product_name} paskyra laikinai išjungta",
|
||||
"body": "Sveikas, {username},\n\nLaikinai išjungėme tavo {product_name} paskyrą, nes aptikome įtartiną veiklą.\n\n{reason, select,\n null {}\n other {Priežastis: {reason}}\n}\n\nNorėdamas atgauti prieigą prie paskyros, turėsi iš naujo nustatyti slaptažodį:\n\n{forgotUrl}\n\nNustatęs slaptažodį iš naujo, galėsi vėl prisijungti.\n\nJei manai, kad tai įvyko per klaidą, susisiek su mūsų palaikymo komanda.\n\n– {product_name} saugos komanda"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_NL_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_NL_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Je {product_name}-account is tijdelijk uitgeschakeld",
|
||||
"body": "Hallo {username},\n\nWe hebben je {product_name}-account tijdelijk uitgeschakeld omdat we verdachte activiteit hebben gedetecteerd.\n\n{reason, select,\n null {}\n other {Reden: {reason}}\n}\n\nOm weer toegang te krijgen tot je account, moet je je wachtwoord opnieuw instellen:\n\n{forgotUrl}\n\nNadat je je wachtwoord opnieuw hebt ingesteld, kun je weer inloggen.\n\nAls je denkt dat dit een fout is, neem dan contact op met ons support-team.\n\n– {product_name} Safety Team"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_NO_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_NO_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "{product_name}-kontoen din er midlertidig deaktivert",
|
||||
"body": "Hei {username},\n\nVi deaktiverte {product_name}-kontoen din midlertidig fordi vi oppdaget mistenkelig aktivitet.\n\n{reason, select,\n null {}\n other {Årsak: {reason}}\n}\n\nFor å få tilgang til kontoen din igjen, må du tilbakestille passordet ditt:\n\n{forgotUrl}\n\nEtter at du har tilbakestilt passordet ditt, kan du logge inn igjen.\n\nHvis du mener dette er en feil, kontakt kundestøtte.\n\n– {product_name} sikkerhetsteam"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_PL_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_PL_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Twoje konto {product_name} zostało tymczasowo wyłączone",
|
||||
"body": "Witaj {username},\n\nTymczasowo wyłączyliśmy Twoje konto {product_name}, ponieważ wykryliśmy podejrzaną aktywność.\n\n{reason, select,\n null {}\n other {Powód: {reason}}\n}\n\nAby odzyskać dostęp do konta, musisz zresetować hasło:\n\n{forgotUrl}\n\nPo zresetowaniu hasła będziesz mógł ponownie się zalogować.\n\nJeśli uważasz, że to błąd, skontaktuj się z naszym zespołem wsparcia.\n\n– Zespół Bezpieczeństwa {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_PT_BR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_PT_BR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Sua conta do {product_name} foi desativada temporariamente",
|
||||
"body": "Olá, {username},\n\nDesativamos temporariamente sua conta do {product_name} porque detectamos atividades suspeitas.\n\n{reason, select,\n null {}\n other {Motivo: {reason}}\n}\n\nPara acessar sua conta novamente, você precisará redefinir sua senha:\n\n{forgotUrl}\n\nDepois de redefinir sua senha, você poderá entrar novamente.\n\nSe você acredita que isso foi um erro, entre em contato com nossa equipe de suporte.\n\n– Equipe de Segurança do {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_RO_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_RO_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Contul tău {product_name} a fost dezactivat temporar",
|
||||
"body": "Salut {username},\n\nAm dezactivat temporar contul tău {product_name} deoarece am detectat activitate suspectă.\n\n{reason, select,\n null {}\n other {Motiv: {reason}}\n}\n\nPentru a recăpăta accesul la contul tău, va trebui să-ți resetezi parola:\n\n{forgotUrl}\n\nDupă ce îți resetezi parola, te vei putea conecta din nou.\n\nDacă crezi că aceasta a fost o eroare, te rugăm să contactezi echipa noastră de suport.\n\n– {product_name} Safety Team"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_RU_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_RU_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Твой аккаунт {product_name} временно отключён",
|
||||
"body": "Привет, {username},\n\nМы временно отключили твой аккаунт {product_name}, так как обнаружили подозрительную активность.\n\n{reason, select,\n null {}\n other {Причина: {reason}}\n}\n\nЧтобы восстановить доступ к аккаунту, тебе нужно сбросить пароль:\n\n{forgotUrl}\n\nПосле сброса пароля ты сможешь снова войти в аккаунт.\n\nЕсли ты считаешь, что это ошибка, пожалуйста, свяжись с нашей службой поддержки.\n\n– Команда безопасности {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_SV_SE_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_SV_SE_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Ditt {product_name}-konto har tillfälligt inaktiverats",
|
||||
"body": "Hej {username},\n\nVi har tillfälligt inaktiverat ditt {product_name}-konto eftersom vi upptäckte misstänkt aktivitet.\n\n{reason, select,\n null {}\n other {Anledning: {reason}}\n}\n\nFör att återfå åtkomst till ditt konto måste du återställa ditt lösenord:\n\n{forgotUrl}\n\nEfter att du har återställt ditt lösenord kan du logga in igen.\n\nOm du anser att detta har skett av misstag, kontakta vårt supportteam.\n\n– {product_name} Safety Team"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_TH_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_TH_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "บัญชี {product_name} ของคุณถูกปิดใช้งานชั่วคราว",
|
||||
"body": "สวัสดี {username},\n\nเราปิดใช้งานบัญชี {product_name} ของคุณชั่วคราว เนื่องจากเราตรวจพบกิจกรรมที่น่าสงสัย\n\n{reason, select,\n null {}\n other {เหตุผล: {reason}}\n}\n\nหากต้องการเข้าถึงบัญชีอีกครั้ง ให้รีเซ็ตรหัสผ่าน:\n\n{forgotUrl}\n\nหลังจากรีเซ็ตรหัสผ่านแล้ว คุณจะสามารถเข้าสู่ระบบได้อีกครั้ง\n\nหากคุณเชื่อว่านี่เป็นข้อผิดพลาด โปรดติดต่อทีมสนับสนุนของเรา\n\n– ทีมความปลอดภัย {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_TR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_TR_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "{product_name} hesabın geçici olarak devre dışı bırakıldı",
|
||||
"body": "Merhaba {username},\n\nŞüpheli etkinlik tespit ettiğimiz için {product_name} hesabını geçici olarak devre dışı bıraktık.\n\n{reason, select,\n null {}\n other {Sebep: {reason}}\n}\n\nHesabına tekrar erişmek için şifreni sıfırlaman gerekiyor:\n\n{forgotUrl}\n\nŞifreni sıfırladıktan sonra tekrar giriş yapabilirsin.\n\nBunun bir hata olduğunu düşünüyorsan, lütfen destek ekibimizle iletişime geç.\n\n– {product_name} Güvenlik Ekibi"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_UK_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_UK_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Твій акаунт {product_name} тимчасово вимкнено",
|
||||
"body": "Привіт, {username},\n\nМи тимчасово вимкнули твій акаунт {product_name}, оскільки виявили підозрілу активність.\n\n{reason, select,\n null {}\n other {Причина: {reason}}\n}\n\nЩоб відновити доступ до акаунту, тобі потрібно скинути пароль:\n\n{forgotUrl}\n\nПісля скидання пароля ти зможеш знову увійти.\n\nЯкщо ти вважаєш, що це помилка, будь ласка, зв'яжися з нашою службою підтримки.\n\n– Команда безпеки {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_VI_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_VI_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "Tài khoản {product_name} của bạn đã bị vô hiệu hóa tạm thời",
|
||||
"body": "Xin chào {username},\n\nChúng tôi đã tạm thời vô hiệu hóa tài khoản {product_name} của bạn vì phát hiện hoạt động đáng ngờ.\n\n{reason, select,\n null {}\n other {Lý do: {reason}}\n}\n\nĐể truy cập lại tài khoản, bạn cần đặt lại mật khẩu:\n\n{forgotUrl}\n\nSau khi đặt lại mật khẩu, bạn sẽ có thể đăng nhập lại.\n\nNếu bạn cho rằng đây là lỗi, vui lòng liên hệ đội ngũ hỗ trợ của chúng tôi.\n\n– Đội ngũ An toàn {product_name}"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_ZH_CN_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_ZH_CN_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "你的 {product_name} 账号已被暂时禁用",
|
||||
"body": "你好 {username},\n\n我们检测到你的 {product_name} 账号存在可疑活动,因此暂时禁用了你的账号。\n\n{reason, select,\n null {}\n other {原因: {reason}}\n}\n\n要重新获得账号访问权限,你需要重置密码:\n\n{forgotUrl}\n\n重置密码后,你将能够再次登录。\n\n如果你认为这是误操作,请联系我们的支持团队。\n\n– {product_name} 安全团队"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineEmailI18nLocaleMessages} from '../EmailI18nMessages';
|
||||
|
||||
export const EMAIL_I18N_ZH_TW_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
const EMAIL_I18N_ZH_TW_MESSAGES = defineEmailI18nLocaleMessages({
|
||||
"account_disabled_suspicious": {
|
||||
"subject": "您的 {product_name} 帳號已暫時停用",
|
||||
"body": "哈囉 {username},\n\n我們偵測到您的 {product_name} 帳號有可疑活動,因此已暫時停用您的帳號。\n\n{reason, select,\n null {}\n other {原因:{reason}}\n}\n\n若要重新取得帳號存取權,您需要重設密碼:\n\n{forgotUrl}\n\n重設密碼後,您將可以再次登入。\n\n如果您認為這是錯誤操作,請聯絡我們的支援團隊。\n\n– {product_name} 安全團隊"
|
||||
|
||||
@@ -16,112 +16,8 @@ interface IRateLimitStore {
|
||||
scan(pattern: string, count: number): Promise<Array<string>>;
|
||||
}
|
||||
|
||||
interface InMemoryLeakyBucketState {
|
||||
level: number;
|
||||
updatedAtMs: number;
|
||||
}
|
||||
|
||||
interface RateLimitServiceOptions {
|
||||
globalWindowMs?: number;
|
||||
getCurrentTimeMs?: () => number;
|
||||
}
|
||||
|
||||
class InMemoryRateLimitStore implements IRateLimitStore {
|
||||
private readonly leakyBucketState = new Map<string, InMemoryLeakyBucketState>();
|
||||
|
||||
constructor(private readonly getCurrentTimeMs: () => number = () => Date.now()) {}
|
||||
|
||||
async checkLeakyBucketLimit(key: string, limit: number, windowMs: number, cost: number): Promise<KVRateLimitResult> {
|
||||
const nowMs = this.getCurrentTimeMs();
|
||||
const capacity = Math.max(1, Math.floor(limit));
|
||||
const leakWindowMs = Math.max(1, Math.floor(windowMs));
|
||||
let bucket = this.leakyBucketState.get(key);
|
||||
if (!bucket) {
|
||||
bucket = {level: 0, updatedAtMs: nowMs};
|
||||
this.leakyBucketState.set(key, bucket);
|
||||
}
|
||||
drainLeakyBucket(bucket, capacity, leakWindowMs, nowMs);
|
||||
if (cost <= 0) {
|
||||
const remaining = Math.max(0, Math.floor(capacity - bucket.level));
|
||||
const resetAfterMs = leakyBucketResetAfterMs(bucket, capacity, leakWindowMs);
|
||||
return createStoreResult(true, capacity, remaining, nowMs, resetAfterMs, 0);
|
||||
}
|
||||
if (cost !== 1) {
|
||||
throw new Error(`Unsupported leaky bucket cost: ${cost}`);
|
||||
}
|
||||
if (bucket.level + cost > capacity) {
|
||||
const retryAfterMs = leakyBucketRetryAfterMs(bucket, capacity, leakWindowMs, cost);
|
||||
const resetAfterMs = leakyBucketResetAfterMs(bucket, capacity, leakWindowMs);
|
||||
return createStoreResult(false, capacity, 0, nowMs, Math.max(resetAfterMs, retryAfterMs), retryAfterMs);
|
||||
}
|
||||
bucket.level += cost;
|
||||
const remaining = Math.max(0, Math.floor(capacity - bucket.level));
|
||||
const resetAfterMs = leakyBucketResetAfterMs(bucket, capacity, leakWindowMs);
|
||||
return createStoreResult(true, capacity, remaining, nowMs, resetAfterMs, 0);
|
||||
}
|
||||
|
||||
async del(...keys: Array<string>): Promise<number> {
|
||||
let deleted = 0;
|
||||
for (const key of keys) {
|
||||
const deletedBucket = this.leakyBucketState.delete(key);
|
||||
if (deletedBucket) {
|
||||
deleted++;
|
||||
}
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
async scan(pattern: string, count: number): Promise<Array<string>> {
|
||||
const limit = Math.max(1, Math.floor(count));
|
||||
const matcher = compileGlobMatcher(pattern);
|
||||
const matches = new Set<string>();
|
||||
for (const key of this.leakyBucketState.keys()) {
|
||||
if (matcher(key)) {
|
||||
matches.add(key);
|
||||
if (matches.size >= limit) break;
|
||||
}
|
||||
}
|
||||
return Array.from(matches);
|
||||
}
|
||||
}
|
||||
|
||||
function compileGlobMatcher(pattern: string): (key: string) => boolean {
|
||||
const escaped = pattern
|
||||
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
||||
.replace(/\*/g, '.*')
|
||||
.replace(/\?/g, '.');
|
||||
const regex = new RegExp(`^${escaped}$`);
|
||||
return (key: string) => regex.test(key);
|
||||
}
|
||||
|
||||
function drainLeakyBucket(bucket: InMemoryLeakyBucketState, capacity: number, windowMs: number, nowMs: number): void {
|
||||
const elapsed = nowMs - bucket.updatedAtMs;
|
||||
if (elapsed <= 0) {
|
||||
return;
|
||||
}
|
||||
const leaked = (elapsed / windowMs) * capacity;
|
||||
bucket.level = Math.max(0, bucket.level - leaked);
|
||||
bucket.updatedAtMs = nowMs;
|
||||
}
|
||||
|
||||
function leakyBucketRetryAfterMs(
|
||||
bucket: InMemoryLeakyBucketState,
|
||||
capacity: number,
|
||||
windowMs: number,
|
||||
cost: number,
|
||||
): number {
|
||||
const overflow = bucket.level + cost - capacity;
|
||||
if (overflow <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(1, Math.ceil(overflow / (capacity / windowMs)));
|
||||
}
|
||||
|
||||
function leakyBucketResetAfterMs(bucket: InMemoryLeakyBucketState, capacity: number, windowMs: number): number {
|
||||
if (bucket.level <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(0, Math.ceil(bucket.level / (capacity / windowMs)));
|
||||
}
|
||||
|
||||
function millisecondsToDecimalSeconds(milliseconds: number): number {
|
||||
@@ -131,24 +27,6 @@ function millisecondsToDecimalSeconds(milliseconds: number): number {
|
||||
return milliseconds / 1000;
|
||||
}
|
||||
|
||||
function createStoreResult(
|
||||
allowed: boolean,
|
||||
limit: number,
|
||||
remaining: number,
|
||||
nowMs: number,
|
||||
resetAfterMs: number,
|
||||
retryAfterMs: number,
|
||||
): KVRateLimitResult {
|
||||
return {
|
||||
allowed,
|
||||
limit,
|
||||
remaining,
|
||||
resetAfterMs,
|
||||
resetAtMs: nowMs + resetAfterMs,
|
||||
retryAfterMs,
|
||||
};
|
||||
}
|
||||
|
||||
function createRateLimitResult(result: KVRateLimitResult, global?: boolean): RateLimitResult {
|
||||
const resetAfterDecimal = millisecondsToDecimalSeconds(result.resetAfterMs);
|
||||
const retryAfterDecimal = millisecondsToDecimalSeconds(result.retryAfterMs);
|
||||
@@ -224,23 +102,3 @@ export class RateLimitService implements IRateLimitService {
|
||||
return totalDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
function createRateLimitService(
|
||||
store: IRateLimitStore | null,
|
||||
options: RateLimitServiceOptions = {},
|
||||
): RateLimitService | null {
|
||||
if (!store) {
|
||||
return null;
|
||||
}
|
||||
return new RateLimitService(store, options);
|
||||
}
|
||||
|
||||
export function createInMemoryRateLimitService(
|
||||
enabled: boolean,
|
||||
options: RateLimitServiceOptions = {},
|
||||
): RateLimitService | null {
|
||||
if (!enabled) {
|
||||
return null;
|
||||
}
|
||||
return createRateLimitService(new InMemoryRateLimitStore(options.getCurrentTimeMs), options);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,12 @@ describe('Email verification flow', () => {
|
||||
await harness?.shutdown();
|
||||
});
|
||||
it('allows resending verification email and verifying email', async () => {
|
||||
const account = await createTestAccount(harness);
|
||||
const account = await createTestAccount(harness, {skipEmailVerification: true});
|
||||
await createBuilderWithoutAuth(harness)
|
||||
.post(`/test/users/${account.userId}/security-flags`)
|
||||
.body({email_verified: false})
|
||||
.expect(200)
|
||||
.execute();
|
||||
await createBuilder(harness, account.token).post('/auth/verify/resend').body({}).expect(204).execute();
|
||||
const emails = await listTestEmails(harness, {recipient: account.email});
|
||||
const verificationEmail = findLastTestEmail(emails, 'email_verification');
|
||||
|
||||
@@ -22,8 +22,17 @@ describe('MFA requires verified email', () => {
|
||||
afterAll(async () => {
|
||||
await harness?.shutdown();
|
||||
});
|
||||
it('rejects TOTP enablement for unverified accounts', async () => {
|
||||
async function createUnverifiedAccount() {
|
||||
const account = await createTestAccount(harness, {skipEmailVerification: true});
|
||||
await createBuilder(harness, '')
|
||||
.post(`/test/users/${account.userId}/security-flags`)
|
||||
.body({email_verified: false})
|
||||
.expect(200)
|
||||
.execute();
|
||||
return account;
|
||||
}
|
||||
it('rejects TOTP enablement for unverified accounts', async () => {
|
||||
const account = await createUnverifiedAccount();
|
||||
const secret = createTotpSecret();
|
||||
const {json} = await createBuilder<ErrorResponse>(harness, account.token)
|
||||
.post('/users/@me/mfa/totp/enable')
|
||||
@@ -33,7 +42,7 @@ describe('MFA requires verified email', () => {
|
||||
expect(json.code).toBe(APIErrorCodes.MFA_EMAIL_VERIFICATION_REQUIRED);
|
||||
});
|
||||
it('rejects WebAuthn registration setup for unverified accounts', async () => {
|
||||
const account = await createTestAccount(harness, {skipEmailVerification: true});
|
||||
const account = await createUnverifiedAccount();
|
||||
const {json} = await createBuilder<ErrorResponse>(harness, account.token)
|
||||
.post('/users/@me/mfa/webauthn/credentials/registration-options')
|
||||
.body({password: account.password})
|
||||
|
||||
@@ -187,7 +187,9 @@ describe('Phone verification flow', () => {
|
||||
await allowPhoneVerification(account.userId);
|
||||
const config = getConfig();
|
||||
const previousInboundNumber = config.sms.inboundChallengeNumber;
|
||||
const previousInboundPrefixes = config.abusePolicy.phoneVerification.inboundRequiredPrefixes;
|
||||
config.sms.inboundChallengeNumber = '+15551234567';
|
||||
config.abusePolicy.phoneVerification.inboundRequiredPrefixes = ['+998'];
|
||||
try {
|
||||
const response = await createBuilder<{
|
||||
channel: string;
|
||||
@@ -207,6 +209,7 @@ describe('Phone verification flow', () => {
|
||||
expect(response.challenge_code).toMatch(/^\d{6}$/);
|
||||
} finally {
|
||||
config.sms.inboundChallengeNumber = previousInboundNumber;
|
||||
config.abusePolicy.phoneVerification.inboundRequiredPrefixes = previousInboundPrefixes;
|
||||
}
|
||||
});
|
||||
it('does not let clients force SMS for inbound-only prefixes', async () => {
|
||||
@@ -214,7 +217,9 @@ describe('Phone verification flow', () => {
|
||||
await allowPhoneVerification(account.userId);
|
||||
const config = getConfig();
|
||||
const previousInboundNumber = config.sms.inboundChallengeNumber;
|
||||
const previousInboundPrefixes = config.abusePolicy.phoneVerification.inboundRequiredPrefixes;
|
||||
config.sms.inboundChallengeNumber = '+15551234567';
|
||||
config.abusePolicy.phoneVerification.inboundRequiredPrefixes = ['+593'];
|
||||
try {
|
||||
const response = await createBuilder<{
|
||||
channel: string;
|
||||
@@ -233,6 +238,7 @@ describe('Phone verification flow', () => {
|
||||
});
|
||||
} finally {
|
||||
config.sms.inboundChallengeNumber = previousInboundNumber;
|
||||
config.abusePolicy.phoneVerification.inboundRequiredPrefixes = previousInboundPrefixes;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -308,19 +308,6 @@ export async function createGroupDmChannel(
|
||||
return channel;
|
||||
}
|
||||
|
||||
export async function addRecipientToGroupDm(
|
||||
harness: ApiTestHarness,
|
||||
token: string,
|
||||
channelId: string,
|
||||
userId: string,
|
||||
): Promise<void> {
|
||||
await createBuilder(harness, token)
|
||||
.put(`/channels/${channelId}/recipients/${userId}`)
|
||||
.body(null)
|
||||
.expect(204)
|
||||
.execute();
|
||||
}
|
||||
|
||||
export async function updateUserSettings(
|
||||
harness: ApiTestHarness,
|
||||
token: string,
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {GuildFeatures} from '@fluxer/constants/src/GuildConstants';
|
||||
import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import {LIMIT_KEYS} from '@fluxer/constants/src/LimitConfigMetadata';
|
||||
import {MAX_GUILD_MEMBERS_VERY_LARGE_GUILD} from '@fluxer/constants/src/LimitConstants';
|
||||
import {DEFAULT_RESTRICTED_LIMITS, DEFAULT_STOCK_LIMITS} from '@fluxer/limits/src/LimitDefaults';
|
||||
import type {LimitConfigSnapshot, LimitRule} from '@fluxer/limits/src/LimitTypes';
|
||||
|
||||
const LIMIT_RULE_IDS = {
|
||||
DEFAULT: 'default',
|
||||
HOSTED_UPGRADE: 'premium',
|
||||
VERY_LARGE_GUILD: 'very_large_guild',
|
||||
} as const;
|
||||
|
||||
export interface CachedLimitConfig {
|
||||
@@ -73,12 +76,22 @@ export function createDefaultLimitConfig(options?: {
|
||||
id: LIMIT_RULE_IDS.DEFAULT,
|
||||
limits: {...DEFAULT_RESTRICTED_LIMITS},
|
||||
},
|
||||
{
|
||||
id: LIMIT_RULE_IDS.VERY_LARGE_GUILD,
|
||||
filters: {guildFeatures: [GuildFeatures.VERY_LARGE_GUILD]},
|
||||
limits: {max_guild_members: MAX_GUILD_MEMBERS_VERY_LARGE_GUILD},
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
id: LIMIT_RULE_IDS.DEFAULT,
|
||||
limits: {...DEFAULT_STOCK_LIMITS},
|
||||
},
|
||||
{
|
||||
id: LIMIT_RULE_IDS.VERY_LARGE_GUILD,
|
||||
filters: {guildFeatures: [GuildFeatures.VERY_LARGE_GUILD]},
|
||||
limits: {max_guild_members: MAX_GUILD_MEMBERS_VERY_LARGE_GUILD},
|
||||
},
|
||||
],
|
||||
};
|
||||
return sanitizeLimitConfigForInstance(cloneLimitConfigSnapshot(hostedDefault), {selfHosted, premiumMode});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_AR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_AR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "إذا كنت مستهلكًا في الاتحاد الأوروبي/المنطقة الاقتصادية الأوروبية، فإنني أوافق صراحةً على تقديم المحتوى الرقمي لـ {product_name} {premium_tier_name} فورًا، وأقرّ بأنني أفقد حقي القانوني في الانسحاب بمجرد تقديم الوصول. لا يؤثر هذا على حقوق المستهلك الإلزامية الأخرى. اطّلع على [شروط الخدمة]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "انتهينا من حذف رسائلك. أزلنا {message_count, plural, =0 {0 رسالة} one {رسالة واحدة} two {رسالتين} few {# رسائل} many {# رسالة} other {# رسالة}} من {channel_count, plural, =0 {0 مكان} one {مكان واحد} two {مكانين} few {# أماكن} many {# مكانًا} other {# مكان}}.",
|
||||
"content.virus_detected": "تم الإبلاغ عن هذا الملف على أنه قد يكون غير آمن وتمت إزالته.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_BG_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_BG_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Ако съм потребител от ЕС/ЕИП, изрично се съгласявам цифровото съдържание на {product_name} {premium_tier_name} да бъде предоставено незабавно и признавам, че губя законното си право на отказ, след като достъпът бъде предоставен. Това не засяга други задължителни потребителски права. Виж [Условията за ползване]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Изтриването на съобщенията ти приключи. Премахнахме {message_count, plural, =0 {0 съобщения} one {# съобщение} other {# съобщения}} от {channel_count, plural, =0 {0 места} one {# място} other {# места}}.",
|
||||
"content.virus_detected": "Този файл беше маркиран като потенциално опасен и е премахнат.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_CS_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_CS_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Pokud jsem spotřebitelem z EU/EHP, výslovně souhlasím s tím, že digitální obsah {product_name} {premium_tier_name} bude poskytnut okamžitě, a beru na vědomí, že po poskytnutí přístupu ztrácím zákonné právo na odstoupení od smlouvy. Tím nejsou dotčena další povinná práva spotřebitele. Viz [Podmínky služby]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Dokončili jsme mazání tvých zpráv. Odstranili jsme {message_count, plural, =0 {0 zpráv} one {# zprávu} few {# zprávy} many {# zpráv} other {# zpráv}} z {channel_count, plural, =0 {0 míst} one {# místa} few {# míst} many {# míst} other {# míst}}.",
|
||||
"content.virus_detected": "Tento soubor byl označen jako potenciálně nebezpečný a byl odstraněn.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_DA_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_DA_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Hvis jeg er en EU/EØS-forbruger, giver jeg udtrykkeligt samtykke til, at {product_name}s {premium_tier_name}-abonnement digitalt indhold leveres øjeblikkeligt, og jeg anerkender, at jeg mister min lovbestemte fortrydelsesret, når adgangen gives. Dette påvirker ikke andre ufravigelige forbrugerrettigheder. Se [servicevilkårene]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Vi er færdige med at slette dine beskeder. Vi fjernede {message_count, plural, =0 {0 beskeder} one {# besked} other {# beskeder}} fra {channel_count, plural, =0 {0 steder} one {# sted} other {# steder}}.",
|
||||
"content.virus_detected": "Den fil blev markeret som potentielt usikker og er blevet fjernet.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_DE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_DE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Als EU/EWR-Verbraucher stimmst du ausdrücklich zu, dass {product_name} {premium_tier_name} digitale Inhalte sofort bereitgestellt werden, und erkennst an, dass dein gesetzliches Widerrufsrecht erlischt, sobald der Zugriff gewährt wird. Dies berührt nicht andere zwingende Verbraucherrechte. Sieh dir die [Nutzungsbedingungen]({terms_url}) an.",
|
||||
"bulk_message_deletion.complete": "Wir haben deine Nachrichten gelöscht. Entfernt wurden {message_count, plural, =0 {0 Nachrichten} one {# Nachricht} other {# Nachrichten}} aus {channel_count, plural, =0 {0 Orten} one {# Ort} other {# Orten}}.",
|
||||
"content.virus_detected": "Diese Datei wurde als potenziell unsicher eingestuft und entfernt.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_EL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_EL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Αν είμαι καταναλωτής ΕΕ/ΕΟΧ, συναινώ ρητά στην άμεση παροχή του ψηφιακού περιεχομένου του πλάνου {premium_tier_name} του {product_name} και αναγνωρίζω ότι χάνω το νόμιμο δικαίωμα υπαναχώρησης μόλις παρασχεθεί η πρόσβαση. Αυτό δεν επηρεάζει άλλα υποχρεωτικά δικαιώματα των καταναλωτών. Ανατρέξτε στους [Όρους Παροχής Υπηρεσιών]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Ολοκληρώσαμε τη διαγραφή των μηνυμάτων σου. Αφαιρέσαμε {message_count, plural, =0 {0 μηνύματα} one {# μήνυμα} other {# μηνύματα}} από {channel_count, plural, =0 {0 τοποθεσίες} one {# τοποθεσία} other {# τοποθεσίες}}.",
|
||||
"content.virus_detected": "Αυτό το αρχείο επισημάνθηκε ως δυνητικά μη ασφαλές και έχει αφαιρεθεί.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_EN_GB_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_EN_GB_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "If I am an EU/EEA consumer, I expressly consent to {product_name} {premium_tier_name} digital content being provided immediately and acknowledge that I lose my statutory withdrawal right once access is provided. This does not affect other mandatory consumer rights. See the [Terms of Service]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "We've finished deleting your messages. We removed {message_count, plural, =0 {0 messages} one {# message} other {# messages}} from {channel_count, plural, =0 {0 places} one {# place} other {# places}}.",
|
||||
"content.virus_detected": "That file was flagged as potentially unsafe and has been removed.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_ES_419_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_ES_419_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Si soy un consumidor de la UE/EEE, doy mi consentimiento expreso para que el contenido digital de {product_name} {premium_tier_name} se proporcione de inmediato y reconozco que pierdo mi derecho legal de desistimiento una vez que se otorgue el acceso. Esto no afecta otros derechos de consumo obligatorios. Consulta los [Términos de servicio]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Terminamos de eliminar tus mensajes. Eliminamos {message_count, plural, =0 {0 mensajes} one {# mensaje} other {# mensajes}} de {channel_count, plural, =0 {0 lugares} one {# lugar} other {# lugares}}.",
|
||||
"content.virus_detected": "Ese archivo fue marcado como potencialmente inseguro y se ha eliminado.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_ES_ES_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_ES_ES_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Si soy un consumidor de la UE/EEE, doy mi consentimiento expreso para que el contenido digital de {product_name} {premium_tier_name} se proporcione de inmediato y reconozco que pierdo mi derecho legal de desistimiento una vez que se conceda el acceso. Esto no afecta a otros derechos de consumo obligatorios. Consulta los [Términos del servicio]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Hemos terminado de eliminar tus mensajes. Hemos eliminado {message_count, plural, =0 {0 mensajes} one {# mensaje} other {# mensajes}} de {channel_count, plural, =0 {0 sitios} one {# sitio} other {# sitios}}.",
|
||||
"content.virus_detected": "Ese archivo se ha marcado como potencialmente inseguro y se ha eliminado.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_FI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_FI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Jos olen EU/ETA-kuluttaja, annan nimenomaisen suostumukseni sille, että {product_name}-tuotteen {premium_tier_name} digitaalinen sisältö toimitetaan välittömästi, ja hyväksyn, että menetän lakisääteisen peruutusoikeuteni, kun pääsy on myönnetty. Tämä ei vaikuta muihin pakollisiin kuluttajaoikeuksiin. Katso [käyttöehdot]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Olemme poistaneet viestisi. Poistimme {message_count, plural, =0 {0 viestiä} one {# viestin} other {# viestiä}} {channel_count, plural, =0 {0 paikasta} one {# paikasta} other {# paikasta}}.",
|
||||
"content.virus_detected": "Tiedosto merkittiin mahdollisesti vaaralliseksi ja se on poistettu.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_FR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_FR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "En tant que consommateur UE/EEE, je consens expressément à ce que le contenu numérique {product_name} {premium_tier_name} soit fourni immédiatement et reconnais perdre mon droit de rétractation légal dès l'accès fourni. Cela n'affecte pas les autres droits impératifs des consommateurs. Voir les [Conditions d'utilisation]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Nous avons terminé la suppression de tes messages. Nous avons retiré {message_count, plural, =0 {0 message} one {# message} other {# messages}} dans {channel_count, plural, =0 {0 endroit} one {# endroit} other {# endroits}}.",
|
||||
"content.virus_detected": "Ce fichier a été signalé comme potentiellement dangereux et a été supprimé.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_HE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_HE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "אם אני צרכן באיחוד האירופי/EEA, אני מסכים במפורש לכך שתוכן דיגיטלי של {product_name} {premium_tier_name} יסופק באופן מיידי ומאשר שאני מאבד את זכות הביטול הסטטוטורית שלי מרגע שהגישה ניתנת. אין בכך כדי לפגוע בזכויות צרכניות מחייבות אחרות. ראו [תנאי השירות]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "סיימנו למחוק את ההודעות שלך. הסרנו {message_count, plural, =0 {0 הודעות} one {הודעה אחת} two {שתי הודעות} other {# הודעות}} מתוך {channel_count, plural, =0 {0 מקומות} one {מקום אחד} two {שני מקומות} other {# מקומות}}.",
|
||||
"content.virus_detected": "הקובץ הזה סומן כחשוד והוסר.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_HI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_HI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "अगर मैं EU/EEA का उपभोक्ता हूँ, तो मैं {product_name} {premium_tier_name} डिजिटल कंटेंट को तुरंत उपलब्ध कराने के लिए स्पष्ट रूप से सहमति देता हूँ और स्वीकार करता हूँ कि एक्सेस मिलने के बाद मेरा वैधानिक वापसी का अधिकार समाप्त हो जाता है। इससे अन्य अनिवार्य उपभोक्ता अधिकार प्रभावित नहीं होते। [सेवा की शर्तें]({terms_url}) देखें।",
|
||||
"bulk_message_deletion.complete": "हमने आपके संदेश हटाने का काम पूरा कर लिया है। हमने {channel_count, plural, =0 {0 जगहों से} one {# जगह से} other {# जगहों से}} {message_count, plural, =0 {0 संदेश} one {# संदेश} other {# संदेश}} हटा दिए।",
|
||||
"content.virus_detected": "वह फाइल संभावित रूप से असुरक्षित पाई गई और उसे हटा दिया गया है।",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_HR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_HR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Ako si potrošač iz EU/EEA, izričito pristaješ na trenutačnu isporuku digitalnog sadržaja {product_name} pretplate {premium_tier_name} i prihvaćaš da gubiš zakonsko pravo na odustanak čim ti se omogući pristup. To ne utječe na ostala obvezna potrošačka prava. Pogledaj [Uvjete pružanja usluge]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Završili smo s brisanjem tvojih poruka. Uklonili smo {message_count, plural, =0 {0 poruka} one {# poruku} few {# poruke} other {# poruka}} iz {channel_count, plural, =0 {0 mjesta} one {# mjesta} few {# mjesta} other {# mjesta}}.",
|
||||
"content.virus_detected": "Ta je datoteka označena kao potencijalno nesigurna i uklonjena je.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_HU_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_HU_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Ha EU/EGT-fogyasztó vagyok, kifejezetten hozzájárulok ahhoz, hogy a {product_name} {premium_tier_name} digitális tartalmat azonnal biztosítsák, és tudomásul veszem, hogy a hozzáférés megadásával elveszítem a törvényes elállási jogomat. Ez nem érinti a többi kötelező fogyasztói jogot. Lásd a [Felhasználási feltételeket]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Befejeztük az üzeneteid törlését. Eltávolítottunk {message_count, plural, =0 {0 üzenetet} one {# üzenetet} other {# üzenetet}} {channel_count, plural, =0 {0 helyről} one {# helyről} other {# helyről}}.",
|
||||
"content.virus_detected": "A fájl potenciálisan veszélyesnek minősült, ezért eltávolítottuk.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_ID_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_ID_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Jika saya konsumen EU/EEA, saya setuju konten digital {product_name} paket {premium_tier_name} diberikan segera dan mengakui bahwa saya kehilangan hak pembatalan begitu akses diberikan. Ini tidak memengaruhi hak konsumen wajib lainnya. Lihat [Ketentuan Layanan]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Kami sudah selesai menghapus pesanmu. Kami menghapus {message_count, plural, =0 {0 pesan} other {# pesan}} dari {channel_count, plural, =0 {0 tempat} other {# tempat}}.",
|
||||
"content.virus_detected": "File itu terdeteksi tidak aman dan telah dihapus.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_IT_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_IT_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Se sono un consumatore UE/SEE, acconsento espressamente alla fornitura immediata del contenuto digitale {product_name} {premium_tier_name} e riconosco di perdere il mio diritto di recesso legale una volta che l'accesso viene fornito. Ciò non pregiudica altri diritti dei consumatori previsti dalla legge. Vedi i [Termini di servizio]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Abbiamo finito di eliminare i tuoi messaggi. Abbiamo rimosso {message_count, plural, =0 {0 messaggi} one {# messaggio} other {# messaggi}} da {channel_count, plural, =0 {0 posti} one {# posto} other {# posti}}.",
|
||||
"content.virus_detected": "Il file è stato segnalato come potenzialmente pericoloso ed è stato rimosso.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_JA_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_JA_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "私が EU/EEA の消費者である場合、{product_name} {premium_tier_name} のデジタルコンテンツが直ちに提供されることに明示的に同意し、アクセスが提供された時点で法定のクーリングオフ権を失うことを承諾します。これはその他の強制的な消費者権利に影響を与えません。[利用規約]({terms_url})をご確認ください。",
|
||||
"bulk_message_deletion.complete": "メッセージの削除が完了しました。{channel_count, plural, =0 {0 件の場所から} other {# 件の場所から}}{message_count, plural, =0 {0 件のメッセージを削除しました} other {# 件のメッセージを削除しました}}。",
|
||||
"content.virus_detected": "そのファイルは安全でないと判断されたため、削除されました。",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_KO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_KO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "EU/EEA 소비자로서 {product_name} {premium_tier_name} 디지털 콘텐츠를 즉시 제공받는 데 명시적으로 동의하며, 액세스가 제공된 후에는 법정 철회권을 상실함을 인정합니다. 이는 다른 필수 소비자 권리에 영향을 미치지 않습니다. [서비스 약관]({terms_url})을 확인하세요.",
|
||||
"bulk_message_deletion.complete": "메시지 삭제를 완료했습니다. {channel_count, plural, =0 {0 곳에서} other {# 곳에서}} {message_count, plural, =0 {0 개의 메시지를 삭제했습니다} other {# 개의 메시지를 삭제했습니다}}.",
|
||||
"content.virus_detected": "해당 파일은 잠재적으로 안전하지 않은 것으로 확인되어 삭제되었어요.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_LT_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_LT_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Jei esu ES/EEE vartotojas, aiškiai sutinku, kad {product_name} {premium_tier_name} skaitmeninis turinys būtų suteiktas nedelsiant ir pripažįstu, kad, suteikus prieigą, netenku teisės atsisakyti sutarties. Tai neturi įtakos kitoms privalomoms vartotojų teisėms. Žr. [Paslaugų teikimo sąlygas]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Baigėme trinti tavo žinutes. Pašalinome {message_count, plural, =0 {0 žinučių} one {# žinutę} few {# žinutes} many {# žinutės} other {# žinučių}} iš {channel_count, plural, =0 {0 vietų} one {# vietos} few {# vietų} many {# vietos} other {# vietų}}.",
|
||||
"content.virus_detected": "Failas buvo pažymėtas kaip galimai nesaugus ir pašalintas.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_NL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_NL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Als ik een EU/EER-consument ben, geef ik uitdrukkelijk toestemming dat de digitale inhoud van {product_name} {premium_tier_name} onmiddellijk wordt geleverd en erken ik dat ik mijn wettelijke herroepingsrecht verlies zodra toegang wordt verleend. Dit heeft geen invloed op andere dwingende consumentenrechten. Zie de [Servicevoorwaarden]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "We zijn klaar met het verwijderen van je berichten. We hebben {message_count, plural, =0 {0 berichten} one {# bericht} other {# berichten}} verwijderd uit {channel_count, plural, =0 {0 plekken} one {# plek} other {# plekken}}.",
|
||||
"content.virus_detected": "Dat bestand is gemarkeerd als mogelijk onveilig en is verwijderd.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_NO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_NO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Hvis jeg er en EU/EØS-forbruker, samtykker jeg uttrykkelig til at {product_name} {premium_tier_name} digitalt innhold leveres umiddelbart, og erkjenner at jeg mister min lovbestemte angrerett når tilgangen er gitt. Dette påvirker ikke andre lovpålagte forbrukerrettigheter. Se [tjenestevilkårene]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Vi er ferdige med å slette meldingene dine. Vi fjernet {message_count, plural, =0 {0 meldinger} one {# melding} other {# meldinger}} fra {channel_count, plural, =0 {0 steder} one {# sted} other {# steder}}.",
|
||||
"content.virus_detected": "Filen ble flagget som potensielt utrygg og er fjernet.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_PL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_PL_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Jako konsument z UE/EOG zgadzam się na natychmiastowe dostarczenie treści cyfrowych {product_name} {premium_tier_name} i przyjmuję do wiadomości, że po uzyskaniu dostępu tracę ustawowe prawo do odstąpienia od umowy. Nie wpływa to na inne obowiązkowe prawa konsumenta. Zobacz [Warunki użytkowania]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Zakończyliśmy usuwanie Twoich wiadomości. Usunęliśmy {message_count, plural, =0 {0 wiadomości} one {# wiadomość} few {# wiadomości} many {# wiadomości} other {# wiadomości}} z {channel_count, plural, =0 {0 miejsc} one {# miejsca} few {# miejsc} many {# miejsc} other {# miejsc}}.",
|
||||
"content.virus_detected": "Ten plik został oznaczony jako potencjalnie niebezpieczny i został usunięty.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_PT_BR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_PT_BR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Se eu for um consumidor da UE/EEE, consinto expressamente que o conteúdo digital {product_name} {premium_tier_name} seja fornecido imediatamente e reconheço que perco meu direito legal de arrependimento assim que o acesso for concedido. Isso não afeta outros direitos obrigatórios do consumidor. Consulte os [Termos de Serviço]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Terminamos de excluir suas mensagens. Removemos {message_count, plural, =0 {0 mensagens} one {# mensagem} other {# mensagens}} de {channel_count, plural, =0 {0 lugares} one {# lugar} other {# lugares}}.",
|
||||
"content.virus_detected": "Esse arquivo foi sinalizado como potencialmente inseguro e foi removido.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_RO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_RO_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Dacă sunt un consumator din UE/SEE, îmi exprim consimțământul expres ca conținutul digital {product_name} {premium_tier_name} să fie furnizat imediat și recunosc că pierd dreptul legal de retragere odată ce accesul este acordat. Acest lucru nu afectează alte drepturi obligatorii ale consumatorilor. Vezi [Termenii și condițiile]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Am terminat de șters mesajele tale. Am eliminat {message_count, plural, =0 {0 de mesaje} one {# mesaj} few {# mesaje} other {# de mesaje}} din {channel_count, plural, =0 {0 de locuri} one {# loc} few {# locuri} other {# de locuri}}.",
|
||||
"content.virus_detected": "Acest fișier a fost marcat ca potențial nesigur și a fost eliminat.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_RU_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_RU_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Если ты являешься потребителем из ЕС/ЕЭЗ, ты даёшь явное согласие на немедленное предоставление цифрового контента {product_name} {premium_tier_name} и понимаешь, что теряешь законное право на отмены после получения доступа. Это не затрагивает другие обязательные права потребителя. См. [Условия предоставления услуг]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Мы завершили удаление ваших сообщений. Удалено {message_count, plural, =0 {0 сообщений} one {# сообщение} few {# сообщения} many {# сообщений} other {# сообщений}} из {channel_count, plural, =0 {0 мест} one {# места} few {# мест} many {# мест} other {# мест}}.",
|
||||
"content.virus_detected": "Этот файл был отмечен как потенциально опасный и удалён.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_SV_SE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_SV_SE_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Om jag är en EU/EES-konsument samtycker jag uttryckligen till att {product_name} {premium_tier_name} digitalt innehåll tillhandahålls omedelbart och bekräftar att jag förlorar min lagstadgade ångerrätt när åtkomst ges. Detta påverkar inte andra tvingande konsumenträttigheter. Se [användarvillkoren]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Vi har raderat dina meddelanden. Vi tog bort {message_count, plural, =0 {0 meddelanden} one {# meddelande} other {# meddelanden}} från {channel_count, plural, =0 {0 platser} one {# plats} other {# platser}}.",
|
||||
"content.virus_detected": "Filen flaggades som potentiellt osäker och har tagits bort.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_TH_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_TH_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "หากฉันเป็นผู้บริโภคใน EU/EEA ฉันยินยอมให้มีการให้บริการเนื้อหาดิจิทัล {product_name} {premium_tier_name} ทันที และรับทราบว่าฉันสูญเสียสิทธิ์ในการถอนตัวตามกฎหมายเมื่อมีการให้สิทธิ์การเข้าถึงแล้ว ซึ่งไม่กระทบต่อสิทธิ์ผู้บริโภคอื่นๆ ที่จำเป็น ดู[ข้อกำหนดในการให้บริการ]({terms_url})",
|
||||
"bulk_message_deletion.complete": "ลบข้อความของคุณเรียบร้อยแล้ว เราลบ {message_count, plural, =0 {0 ข้อความ} other {# ข้อความ}} จาก {channel_count, plural, =0 {0 ที่} other {# ที่}}",
|
||||
"content.virus_detected": "ไฟล์นั้นถูกตรวจพบว่าอาจไม่ปลอดภัยและถูกลบออกแล้ว",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_TR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_TR_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "AB/EEA tüketicisiysem, {product_name} {premium_tier_name} dijital içeriğinin hemen sağlanmasına açıkça onay veriyorum ve erişim sağlandıktan sonra yasal cayma hakkımı kaybettiğimi kabul ediyorum. Bu, diğer zorunlu tüketici haklarını etkilemez. [Hizmet Şartları]({terms_url}) sayfasına bakın.",
|
||||
"bulk_message_deletion.complete": "Mesajlarını silme işlemini tamamladık. {channel_count, plural, =0 {0 yerden} one {# yerden} other {# yerden}} {message_count, plural, =0 {0 mesaj} one {# mesaj} other {# mesaj}} kaldırdık.",
|
||||
"content.virus_detected": "Bu dosya potansiyel olarak güvensiz olarak işaretlendi ve kaldırıldı.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_UK_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_UK_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Якщо я є споживачем з ЄС/ЄЕЗ, я надаю явну згоду на негайне надання цифрового контенту {product_name} {premium_tier_name} і визнаю, що втрачаю своє законне право на відмову після отримання доступу. Це не впливає на інші обов'язкові права споживача. Див. [Умови надання послуг]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Ми завершили видалення твоїх повідомлень. Видалено {message_count, plural, =0 {0 повідомлень} one {# повідомлення} few {# повідомлення} many {# повідомлень} other {# повідомлень}} з {channel_count, plural, =0 {0 місць} one {# місця} few {# місць} many {# місць} other {# місць}}.",
|
||||
"content.virus_detected": "Цей файл позначено як потенційно небезпечний, і його вилучено.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_VI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_VI_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "Nếu tôi là người tiêu dùng EU/EEA, tôi đồng ý rõ ràng rằng nội dung kỹ thuật số {product_name} {premium_tier_name} được cung cấp ngay lập tức và thừa nhận rằng tôi mất quyền hủy bỏ theo luật định sau khi có quyền truy cập. Điều này không ảnh hưởng đến các quyền lợi người tiêu dùng bắt buộc khác. Xem [Điều khoản dịch vụ]({terms_url}).",
|
||||
"bulk_message_deletion.complete": "Chúng tôi đã xóa xong tin nhắn của bạn. Đã xóa {message_count, plural, =0 {0 tin nhắn} other {# tin nhắn}} khỏi {channel_count, plural, =0 {0 nơi} other {# nơi}}.",
|
||||
"content.virus_detected": "Tệp đó bị gắn cờ là có khả năng không an toàn và đã bị xóa.",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_ZH_CN_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_ZH_CN_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "如果我是欧盟/欧洲经济区消费者,我明确同意立即提供 {product_name} {premium_tier_name} 数字内容,并知晓一旦获得访问权限,我将失去法定撤销权。这不影响其他强制性消费者权利。请参阅[服务条款]({terms_url})。",
|
||||
"bulk_message_deletion.complete": "我们已删除你的消息。从 {channel_count, plural, =0 {0 个位置} other {# 个位置}} 中移除了 {message_count, plural, =0 {0 条消息} other {# 条消息}}。",
|
||||
"content.virus_detected": "该文件被标记为可能存在风险,已被移除。",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import {defineContentI18nLocaleMessages} from '../ContentI18nMessages';
|
||||
|
||||
export const CONTENT_I18N_ZH_TW_MESSAGES = defineContentI18nLocaleMessages({
|
||||
const CONTENT_I18N_ZH_TW_MESSAGES = defineContentI18nLocaleMessages({
|
||||
"billing.eu_withdrawal_waiver_checkout": "若我是歐盟/歐洲經濟區消費者,我明確同意立即提供 {product_name} {premium_tier_name} 數位內容,並了解一旦取得存取權,即喪失法定撤回權。這不影響其他強制性消費者權益。請參閱[服務條款]({terms_url})。",
|
||||
"bulk_message_deletion.complete": "我們已刪除你的訊息。從 {channel_count, plural, =0 {0 個位置} other {# 個位置}} 中移除了 {message_count, plural, =0 {0 則訊息} other {# 則訊息}}。",
|
||||
"content.virus_detected": "該檔案已被標記為可能不安全,並已移除。",
|
||||
|
||||
@@ -51,10 +51,6 @@ export function setCassandraQueryExecutorForTesting(executor: CassandraQueryExec
|
||||
injectedExecutorForTesting = executor;
|
||||
}
|
||||
|
||||
export function hasCassandraQueryExecutorForTesting(): boolean {
|
||||
return injectedExecutorForTesting !== null;
|
||||
}
|
||||
|
||||
export function resetCassandraQueryExecutorForTesting(): void {
|
||||
injectedExecutorForTesting?.reset?.();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {GuildFeatures} from '@fluxer/constants/src/GuildConstants';
|
||||
import {MAX_GUILD_MEMBERS_VERY_LARGE_GUILD} from '@fluxer/constants/src/LimitConstants';
|
||||
import type {LimitConfigSnapshot, LimitRule} from '@fluxer/limits/src/LimitTypes';
|
||||
import {describe, expect, test} from 'vitest';
|
||||
import {createDefaultLimitConfig, mergeWithCurrentDefaults} from '../../constants/LimitConfig';
|
||||
@@ -13,17 +15,27 @@ interface LegacyLimitConfigSnapshot extends Omit<LimitConfigSnapshot, 'rules'> {
|
||||
}
|
||||
|
||||
describe('Limit config defaults', () => {
|
||||
test('hosted defaults include only premium and default tier limit rules', () => {
|
||||
test('hosted defaults include premium, default, and very large guild limit rules', () => {
|
||||
const config = createDefaultLimitConfig({selfHosted: false});
|
||||
const premiumRule = config.rules.find((rule) => rule.id === 'premium');
|
||||
const defaultRule = config.rules.find((rule) => rule.id === 'default');
|
||||
const veryLargeGuildRule = config.rules.find((rule) => rule.id === 'very_large_guild');
|
||||
expect(premiumRule).toBeDefined();
|
||||
expect(defaultRule).toBeDefined();
|
||||
expect(config.rules.map((rule) => rule.id)).toEqual(['premium', 'default']);
|
||||
expect(veryLargeGuildRule).toMatchObject({
|
||||
filters: {guildFeatures: [GuildFeatures.VERY_LARGE_GUILD]},
|
||||
limits: {max_guild_members: MAX_GUILD_MEMBERS_VERY_LARGE_GUILD},
|
||||
});
|
||||
expect(config.rules.map((rule) => rule.id)).toEqual(['premium', 'default', 'very_large_guild']);
|
||||
});
|
||||
test('self-hosted defaults include only default tier limit rule', () => {
|
||||
test('self-hosted defaults include default and very large guild limit rules', () => {
|
||||
const config = createDefaultLimitConfig({selfHosted: true});
|
||||
expect(config.rules.map((rule) => rule.id)).toEqual(['default']);
|
||||
const veryLargeGuildRule = config.rules.find((rule) => rule.id === 'very_large_guild');
|
||||
expect(veryLargeGuildRule).toMatchObject({
|
||||
filters: {guildFeatures: [GuildFeatures.VERY_LARGE_GUILD]},
|
||||
limits: {max_guild_members: MAX_GUILD_MEMBERS_VERY_LARGE_GUILD},
|
||||
});
|
||||
expect(config.rules.map((rule) => rule.id)).toEqual(['default', 'very_large_guild']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -205,5 +205,5 @@ function findHookOrderHazards(): Array<HookOrderFinding> {
|
||||
describe('React hook order stability', () => {
|
||||
it('keeps guard returns outside hook-bearing component bodies', () => {
|
||||
expect(findHookOrderHazards()).toEqual([]);
|
||||
});
|
||||
}, 10_000);
|
||||
});
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
]},
|
||||
{plt_apps, all_deps},
|
||||
{plt_extra_apps, [
|
||||
crypto, enats, inets, jose, public_key, ranch, ssl
|
||||
crypto, enats, erlcass, inets, jose, public_key, ranch, ssl
|
||||
]},
|
||||
{warnings_file, "dialyzer.ignore-warnings"}
|
||||
]}.
|
||||
|
||||
+1
-3
@@ -205,11 +205,9 @@ active_nodes_for_role(undefined) ->
|
||||
active_nodes_for_role(Role) ->
|
||||
gateway_node_router:active_nodes(Role).
|
||||
|
||||
-spec select_owner_nodes(term(), [node()], pos_integer()) -> [node()].
|
||||
-spec select_owner_nodes(term(), [node(), ...], pos_integer()) -> [node()].
|
||||
select_owner_nodes(Key, CandidateNodes, ReplicaCount) ->
|
||||
case lists:usort(CandidateNodes) of
|
||||
[] ->
|
||||
[];
|
||||
[SingleNode] ->
|
||||
[SingleNode];
|
||||
UniqueNodes when ReplicaCount =:= 1 ->
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
ranch,
|
||||
cowboy,
|
||||
ezstd,
|
||||
erlcass,
|
||||
base64url,
|
||||
enats
|
||||
]},
|
||||
|
||||
@@ -180,7 +180,7 @@ resume_lookup_trace_meta(SessionId) ->
|
||||
session_pid_trace_meta(Pid) ->
|
||||
node_trace_meta(session, node(Pid)).
|
||||
|
||||
-spec node_trace_meta(term(), node()) -> map().
|
||||
-spec node_trace_meta(atom(), node()) -> map().
|
||||
node_trace_meta(Operation, NodeName) ->
|
||||
#{
|
||||
remote => #{
|
||||
@@ -189,13 +189,9 @@ node_trace_meta(Operation, NodeName) ->
|
||||
}
|
||||
}.
|
||||
|
||||
-spec trace_key(term()) -> binary().
|
||||
trace_key(Value) when is_binary(Value) ->
|
||||
Value;
|
||||
trace_key(Value) when is_atom(Value) ->
|
||||
atom_to_binary(Value, utf8);
|
||||
-spec trace_key(atom()) -> binary().
|
||||
trace_key(Value) ->
|
||||
list_to_binary(io_lib:format("~p", [Value])).
|
||||
atom_to_binary(Value, utf8).
|
||||
|
||||
-spec node_pod_name_or_name(node()) -> binary().
|
||||
node_pod_name_or_name(NodeName) ->
|
||||
|
||||
@@ -89,7 +89,6 @@ beam_module_from_info(Info) ->
|
||||
beam_md5(Beam) when is_binary(Beam) ->
|
||||
case beam_lib:md5(Beam) of
|
||||
{ok, {_Module, Md5}} when is_binary(Md5) -> {ok, Md5};
|
||||
{ok, Md5} when is_binary(Md5) -> {ok, Md5};
|
||||
Error -> {error, {beam_md5_failed, Error}}
|
||||
end.
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ fetch_events(BuildSha) when is_binary(BuildSha) ->
|
||||
case erlcass:execute(?STMT_FETCH_EVENTS, [BuildSha]) of
|
||||
{ok, _Columns, Rows} -> {ok, normalize_event_rows(Rows)};
|
||||
ok -> {ok, []};
|
||||
{error, Reason} -> {error, Reason};
|
||||
Other -> {error, {unexpected_fetch_result, Other}}
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
-spec append_event(binary(), binary(), binary(), binary(), binary()) ->
|
||||
@@ -99,8 +98,7 @@ execute_append_event(EventId, Params) ->
|
||||
case erlcass:execute(?STMT_APPEND_EVENT, Params) of
|
||||
ok -> {ok, EventId};
|
||||
{ok, _Columns, _Rows} -> {ok, EventId};
|
||||
{error, Reason} -> {error, Reason};
|
||||
Other -> {error, {unexpected_append_result, Other}}
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
-spec audit_applied(binary(), binary(), binary(), map(), ok | {error, term()}) ->
|
||||
@@ -116,8 +114,7 @@ audit_applied(BuildSha, NodeName, EventId, Summary, Result) when
|
||||
case erlcass:execute(?STMT_AUDIT_APPLIED, Params) of
|
||||
ok -> ok;
|
||||
{ok, _Columns, _Rows} -> ok;
|
||||
{error, Reason} -> {error, Reason};
|
||||
Other -> {error, {unexpected_audit_result, Other}}
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
-spec normalize_event_rows([list()]) -> [map()].
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
{no_opaque, [
|
||||
handle_info/2,
|
||||
handle_connect_ok/4,
|
||||
handle_connect_ok_entry/5,
|
||||
accept_connect_ok/4,
|
||||
ignore_stale_connect_ok/2,
|
||||
handle_ready/4,
|
||||
handle_conn_event_down/2,
|
||||
handle_slot_monitor_down/5,
|
||||
|
||||
@@ -340,8 +340,7 @@ subscribe_to_nats(State) ->
|
||||
subscribe_to_rollout_subject() ->
|
||||
try gateway_nats_rpc:subscribe(?NATS_SUBJECT, <<>>) of
|
||||
{ok, Sid} -> {ok, Sid};
|
||||
{error, Reason} -> {error, Reason};
|
||||
Other -> {error, Other}
|
||||
{error, Reason} -> {error, Reason}
|
||||
catch
|
||||
Class:Reason -> {error, {Class, Reason}}
|
||||
end.
|
||||
|
||||
@@ -52,9 +52,7 @@ upsert_voice_state(ConnectionId, VoiceState, State) ->
|
||||
end,
|
||||
State#{voice_states => VoiceStates}.
|
||||
|
||||
-spec strip_members
|
||||
(map()) -> map();
|
||||
(term()) -> term().
|
||||
-spec strip_members(term()) -> term().
|
||||
strip_members(Data) when is_map(Data) ->
|
||||
Data1 = maps:remove(<<"members">>, Data),
|
||||
maps:remove(<<"member_role_index">>, Data1);
|
||||
|
||||
@@ -34,9 +34,7 @@
|
||||
|
||||
-export_type([guild_data/0]).
|
||||
|
||||
-spec normalize_data
|
||||
(map()) -> guild_data();
|
||||
(term()) -> term().
|
||||
-spec normalize_data(term()) -> term().
|
||||
normalize_data(Data) when is_map(Data) ->
|
||||
Data0 =
|
||||
case guild_data_normalize:guild_data(Data) of
|
||||
|
||||
@@ -40,9 +40,7 @@ channel_index(Data) when is_map(Data) ->
|
||||
channel_index(_) ->
|
||||
#{}.
|
||||
|
||||
-spec put_channels
|
||||
(term(), guild_data()) -> guild_data();
|
||||
(term(), term()) -> term().
|
||||
-spec put_channels(term(), term()) -> term().
|
||||
put_channels(Channels, Data) when is_map(Data) ->
|
||||
ChannelList = lists:filtermap(
|
||||
fun normalize_channel_item/1,
|
||||
|
||||
@@ -37,9 +37,7 @@ role_index(Data) when is_map(Data) ->
|
||||
role_index(_) ->
|
||||
#{}.
|
||||
|
||||
-spec put_roles
|
||||
(term(), guild_data()) -> guild_data();
|
||||
(term(), term()) -> term().
|
||||
-spec put_roles(term(), term()) -> term().
|
||||
put_roles(Roles, Data) when is_map(Data) ->
|
||||
RoleList = [
|
||||
normalize_role(Role)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user