Merge branch 'main' into rei/templatecheck_todisk
This commit is contained in:
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* @element-hq/mas-maintainers
|
||||
56
Cargo.lock
generated
56
Cargo.lock
generated
@@ -3096,7 +3096,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-axum-utils"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -3130,7 +3130,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-cli"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -3203,7 +3203,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-config"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
@@ -3235,7 +3235,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-context"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"console",
|
||||
"opentelemetry",
|
||||
@@ -3251,7 +3251,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-data-model"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"chrono",
|
||||
@@ -3274,7 +3274,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-email"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"lettre",
|
||||
@@ -3285,7 +3285,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-handlers"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"aide",
|
||||
"anyhow",
|
||||
@@ -3365,7 +3365,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-http"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"headers",
|
||||
@@ -3386,7 +3386,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-i18n"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"icu_calendar",
|
||||
@@ -3408,7 +3408,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-i18n-scan"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"clap",
|
||||
@@ -3422,7 +3422,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-iana"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"schemars 0.8.22",
|
||||
"serde",
|
||||
@@ -3430,7 +3430,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-iana-codegen"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3446,7 +3446,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-jose"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"chrono",
|
||||
@@ -3476,7 +3476,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-keystore"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"base64ct",
|
||||
@@ -3504,7 +3504,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-listener"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -3529,7 +3529,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-matrix"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3539,7 +3539,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-matrix-synapse"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3556,7 +3556,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-oidc-client"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"async-trait",
|
||||
@@ -3592,7 +3592,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-policy"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -3609,7 +3609,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-router"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"serde",
|
||||
@@ -3620,7 +3620,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-spa"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"serde",
|
||||
@@ -3629,7 +3629,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-storage"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -3651,7 +3651,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-storage-pg"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
@@ -3679,7 +3679,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-tasks"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -3711,7 +3711,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-templates"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
@@ -3741,7 +3741,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mas-tower"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"http",
|
||||
"opentelemetry",
|
||||
@@ -4011,7 +4011,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oauth2-types"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"base64ct",
|
||||
@@ -6094,7 +6094,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn2mas"
|
||||
version = "1.5.0-rc.1"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
|
||||
60
Cargo.toml
60
Cargo.toml
@@ -9,7 +9,7 @@ members = ["crates/*"]
|
||||
resolver = "2"
|
||||
|
||||
# Updated in the CI with a `sed` command
|
||||
package.version = "1.5.0-rc.1"
|
||||
package.version = "1.5.0"
|
||||
package.license = "AGPL-3.0-only OR LicenseRef-Element-Commercial"
|
||||
package.authors = ["Element Backend Team"]
|
||||
package.edition = "2024"
|
||||
@@ -34,35 +34,35 @@ broken_intra_doc_links = "deny"
|
||||
[workspace.dependencies]
|
||||
|
||||
# Workspace crates
|
||||
mas-axum-utils = { path = "./crates/axum-utils/", version = "=1.5.0-rc.1" }
|
||||
mas-cli = { path = "./crates/cli/", version = "=1.5.0-rc.1" }
|
||||
mas-config = { path = "./crates/config/", version = "=1.5.0-rc.1" }
|
||||
mas-context = { path = "./crates/context/", version = "=1.5.0-rc.1" }
|
||||
mas-data-model = { path = "./crates/data-model/", version = "=1.5.0-rc.1" }
|
||||
mas-email = { path = "./crates/email/", version = "=1.5.0-rc.1" }
|
||||
mas-graphql = { path = "./crates/graphql/", version = "=1.5.0-rc.1" }
|
||||
mas-handlers = { path = "./crates/handlers/", version = "=1.5.0-rc.1" }
|
||||
mas-http = { path = "./crates/http/", version = "=1.5.0-rc.1" }
|
||||
mas-i18n = { path = "./crates/i18n/", version = "=1.5.0-rc.1" }
|
||||
mas-i18n-scan = { path = "./crates/i18n-scan/", version = "=1.5.0-rc.1" }
|
||||
mas-iana = { path = "./crates/iana/", version = "=1.5.0-rc.1" }
|
||||
mas-iana-codegen = { path = "./crates/iana-codegen/", version = "=1.5.0-rc.1" }
|
||||
mas-jose = { path = "./crates/jose/", version = "=1.5.0-rc.1" }
|
||||
mas-keystore = { path = "./crates/keystore/", version = "=1.5.0-rc.1" }
|
||||
mas-listener = { path = "./crates/listener/", version = "=1.5.0-rc.1" }
|
||||
mas-matrix = { path = "./crates/matrix/", version = "=1.5.0-rc.1" }
|
||||
mas-matrix-synapse = { path = "./crates/matrix-synapse/", version = "=1.5.0-rc.1" }
|
||||
mas-oidc-client = { path = "./crates/oidc-client/", version = "=1.5.0-rc.1" }
|
||||
mas-policy = { path = "./crates/policy/", version = "=1.5.0-rc.1" }
|
||||
mas-router = { path = "./crates/router/", version = "=1.5.0-rc.1" }
|
||||
mas-spa = { path = "./crates/spa/", version = "=1.5.0-rc.1" }
|
||||
mas-storage = { path = "./crates/storage/", version = "=1.5.0-rc.1" }
|
||||
mas-storage-pg = { path = "./crates/storage-pg/", version = "=1.5.0-rc.1" }
|
||||
mas-tasks = { path = "./crates/tasks/", version = "=1.5.0-rc.1" }
|
||||
mas-templates = { path = "./crates/templates/", version = "=1.5.0-rc.1" }
|
||||
mas-tower = { path = "./crates/tower/", version = "=1.5.0-rc.1" }
|
||||
oauth2-types = { path = "./crates/oauth2-types/", version = "=1.5.0-rc.1" }
|
||||
syn2mas = { path = "./crates/syn2mas", version = "=1.5.0-rc.1" }
|
||||
mas-axum-utils = { path = "./crates/axum-utils/", version = "=1.5.0" }
|
||||
mas-cli = { path = "./crates/cli/", version = "=1.5.0" }
|
||||
mas-config = { path = "./crates/config/", version = "=1.5.0" }
|
||||
mas-context = { path = "./crates/context/", version = "=1.5.0" }
|
||||
mas-data-model = { path = "./crates/data-model/", version = "=1.5.0" }
|
||||
mas-email = { path = "./crates/email/", version = "=1.5.0" }
|
||||
mas-graphql = { path = "./crates/graphql/", version = "=1.5.0" }
|
||||
mas-handlers = { path = "./crates/handlers/", version = "=1.5.0" }
|
||||
mas-http = { path = "./crates/http/", version = "=1.5.0" }
|
||||
mas-i18n = { path = "./crates/i18n/", version = "=1.5.0" }
|
||||
mas-i18n-scan = { path = "./crates/i18n-scan/", version = "=1.5.0" }
|
||||
mas-iana = { path = "./crates/iana/", version = "=1.5.0" }
|
||||
mas-iana-codegen = { path = "./crates/iana-codegen/", version = "=1.5.0" }
|
||||
mas-jose = { path = "./crates/jose/", version = "=1.5.0" }
|
||||
mas-keystore = { path = "./crates/keystore/", version = "=1.5.0" }
|
||||
mas-listener = { path = "./crates/listener/", version = "=1.5.0" }
|
||||
mas-matrix = { path = "./crates/matrix/", version = "=1.5.0" }
|
||||
mas-matrix-synapse = { path = "./crates/matrix-synapse/", version = "=1.5.0" }
|
||||
mas-oidc-client = { path = "./crates/oidc-client/", version = "=1.5.0" }
|
||||
mas-policy = { path = "./crates/policy/", version = "=1.5.0" }
|
||||
mas-router = { path = "./crates/router/", version = "=1.5.0" }
|
||||
mas-spa = { path = "./crates/spa/", version = "=1.5.0" }
|
||||
mas-storage = { path = "./crates/storage/", version = "=1.5.0" }
|
||||
mas-storage-pg = { path = "./crates/storage-pg/", version = "=1.5.0" }
|
||||
mas-tasks = { path = "./crates/tasks/", version = "=1.5.0" }
|
||||
mas-templates = { path = "./crates/templates/", version = "=1.5.0" }
|
||||
mas-tower = { path = "./crates/tower/", version = "=1.5.0" }
|
||||
oauth2-types = { path = "./crates/oauth2-types/", version = "=1.5.0" }
|
||||
syn2mas = { path = "./crates/syn2mas", version = "=1.5.0" }
|
||||
|
||||
# OpenAPI schema generation and validation
|
||||
[workspace.dependencies.aide]
|
||||
|
||||
@@ -160,8 +160,14 @@ impl Options {
|
||||
)?;
|
||||
|
||||
// Load and compile the templates
|
||||
let templates =
|
||||
templates_from_config(&config.templates, &site_config, &url_builder).await?;
|
||||
let templates = templates_from_config(
|
||||
&config.templates,
|
||||
&site_config,
|
||||
&url_builder,
|
||||
// Don't use strict mode in production yet
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
shutdown.register_reloadable(&templates);
|
||||
|
||||
let http_client = mas_http::reqwest_client();
|
||||
|
||||
@@ -72,8 +72,13 @@ impl Options {
|
||||
&account_config,
|
||||
&captcha_config,
|
||||
)?;
|
||||
let templates =
|
||||
templates_from_config(&template_config, &site_config, &url_builder).await?;
|
||||
let templates = templates_from_config(
|
||||
&template_config,
|
||||
&site_config,
|
||||
&url_builder, // Use strict mode in template checks
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
let all_renders = templates.check_render(clock.now(), &mut rng)?;
|
||||
|
||||
if let Some(out_dir) = out_dir {
|
||||
|
||||
@@ -52,8 +52,14 @@ impl Options {
|
||||
)?;
|
||||
|
||||
// Load and compile the templates
|
||||
let templates =
|
||||
templates_from_config(&config.templates, &site_config, &url_builder).await?;
|
||||
let templates = templates_from_config(
|
||||
&config.templates,
|
||||
&site_config,
|
||||
&url_builder,
|
||||
// Don't use strict mode on task workers for now
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mailer = mailer_from_config(&config.email, &templates)?;
|
||||
test_mailer_in_background(&mailer, Duration::from_secs(30));
|
||||
|
||||
@@ -232,6 +232,7 @@ pub async fn templates_from_config(
|
||||
config: &TemplatesConfig,
|
||||
site_config: &SiteConfig,
|
||||
url_builder: &UrlBuilder,
|
||||
strict: bool,
|
||||
) -> Result<Templates, anyhow::Error> {
|
||||
Templates::load(
|
||||
config.path.clone(),
|
||||
@@ -240,6 +241,7 @@ pub async fn templates_from_config(
|
||||
config.translations_path.clone(),
|
||||
site_config.templates_branding(),
|
||||
site_config.templates_features(),
|
||||
strict,
|
||||
)
|
||||
.await
|
||||
.with_context(|| format!("Failed to load the templates at {}", config.path))
|
||||
|
||||
@@ -176,6 +176,8 @@ impl TestState {
|
||||
workspace_root.join("translations"),
|
||||
site_config.templates_branding(),
|
||||
site_config.templates_features(),
|
||||
// Strict mode in testing
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -58,9 +58,9 @@ impl Object for SiteBranding {
|
||||
fn get_value(self: &Arc<Self>, name: &Value) -> Option<Value> {
|
||||
match name.as_str()? {
|
||||
"server_name" => Some(self.server_name.clone().into()),
|
||||
"policy_uri" => self.policy_uri.clone().map(Value::from),
|
||||
"tos_uri" => self.tos_uri.clone().map(Value::from),
|
||||
"imprint" => self.imprint.clone().map(Value::from),
|
||||
"policy_uri" => Some(Value::from(self.policy_uri.clone())),
|
||||
"tos_uri" => Some(Value::from(self.tos_uri.clone())),
|
||||
"imprint" => Some(Value::from(self.imprint.clone())),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use camino::{Utf8Path, Utf8PathBuf};
|
||||
use mas_i18n::Translator;
|
||||
use mas_router::UrlBuilder;
|
||||
use mas_spa::ViteManifest;
|
||||
use minijinja::Value;
|
||||
use minijinja::{UndefinedBehavior, Value};
|
||||
use rand::Rng;
|
||||
use serde::Serialize;
|
||||
use thiserror::Error;
|
||||
@@ -75,6 +75,9 @@ pub struct Templates {
|
||||
vite_manifest_path: Utf8PathBuf,
|
||||
translations_path: Utf8PathBuf,
|
||||
path: Utf8PathBuf,
|
||||
/// Whether template rendering is in strict mode (for testing,
|
||||
/// until this can be rolled out in production.)
|
||||
strict: bool,
|
||||
}
|
||||
|
||||
/// There was an issue while loading the templates
|
||||
@@ -155,6 +158,7 @@ impl Templates {
|
||||
translations_path: Utf8PathBuf,
|
||||
branding: SiteBranding,
|
||||
features: SiteFeatures,
|
||||
strict: bool,
|
||||
) -> Result<Self, TemplateLoadingError> {
|
||||
let (translator, environment) = Self::load_(
|
||||
&path,
|
||||
@@ -163,6 +167,7 @@ impl Templates {
|
||||
&translations_path,
|
||||
branding.clone(),
|
||||
features,
|
||||
strict,
|
||||
)
|
||||
.await?;
|
||||
Ok(Self {
|
||||
@@ -174,6 +179,7 @@ impl Templates {
|
||||
translations_path,
|
||||
branding,
|
||||
features,
|
||||
strict,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -184,6 +190,7 @@ impl Templates {
|
||||
translations_path: &Utf8Path,
|
||||
branding: SiteBranding,
|
||||
features: SiteFeatures,
|
||||
strict: bool,
|
||||
) -> Result<(Arc<Translator>, Arc<minijinja::Environment<'static>>), TemplateLoadingError> {
|
||||
let path = path.to_owned();
|
||||
let span = tracing::Span::current();
|
||||
@@ -209,6 +216,15 @@ impl Templates {
|
||||
span.in_scope(move || {
|
||||
let mut loaded: HashSet<_> = HashSet::new();
|
||||
let mut env = minijinja::Environment::new();
|
||||
// Don't allow use of undefined variables
|
||||
env.set_undefined_behavior(if strict {
|
||||
UndefinedBehavior::Strict
|
||||
} else {
|
||||
// For now, allow semi-strict, because we don't have total test coverage of
|
||||
// tests and some tests rely on if conditions against sometimes-undefined
|
||||
// variables
|
||||
UndefinedBehavior::SemiStrict
|
||||
});
|
||||
let root = path.canonicalize_utf8()?;
|
||||
info!(%root, "Loading templates from filesystem");
|
||||
for entry in walkdir::WalkDir::new(&root)
|
||||
@@ -279,6 +295,7 @@ impl Templates {
|
||||
&self.translations_path,
|
||||
self.branding.clone(),
|
||||
self.features,
|
||||
self.strict,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -495,6 +512,8 @@ mod tests {
|
||||
translations_path,
|
||||
branding,
|
||||
features,
|
||||
// Use strict mode in tests
|
||||
true,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -27,7 +27,7 @@ export type LocalazyMetadata = {
|
||||
};
|
||||
|
||||
const localazyMetadata: LocalazyMetadata = {
|
||||
projectUrl: "https://localazy.com/p/matrix-authentication-service",
|
||||
projectUrl: "https://localazy.com/p/matrix-authentication-service!v1.5",
|
||||
baseLocale: "en",
|
||||
languages: [
|
||||
{
|
||||
@@ -172,21 +172,21 @@ const localazyMetadata: LocalazyMetadata = {
|
||||
file: "frontend.json",
|
||||
path: "",
|
||||
cdnFiles: {
|
||||
"cs": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/cs/frontend.json",
|
||||
"da": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/da/frontend.json",
|
||||
"de": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/de/frontend.json",
|
||||
"en": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/en/frontend.json",
|
||||
"et": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/et/frontend.json",
|
||||
"fi": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fi/frontend.json",
|
||||
"fr": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fr/frontend.json",
|
||||
"hu": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/hu/frontend.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nb-NO/frontend.json",
|
||||
"nl": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nl/frontend.json",
|
||||
"pt": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pt/frontend.json",
|
||||
"ru": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/ru/frontend.json",
|
||||
"sv": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/sv/frontend.json",
|
||||
"uk": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/uk/frontend.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/zh-Hans/frontend.json"
|
||||
"cs": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/cs/frontend.json",
|
||||
"da": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/da/frontend.json",
|
||||
"de": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/de/frontend.json",
|
||||
"en": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/en/frontend.json",
|
||||
"et": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/et/frontend.json",
|
||||
"fi": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fi/frontend.json",
|
||||
"fr": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/fr/frontend.json",
|
||||
"hu": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/hu/frontend.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nb-NO/frontend.json",
|
||||
"nl": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/nl/frontend.json",
|
||||
"pt": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/pt/frontend.json",
|
||||
"ru": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/ru/frontend.json",
|
||||
"sv": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/sv/frontend.json",
|
||||
"uk": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/uk/frontend.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/7c203a8ac8bd48c3c4609a8effcd0fbac430f9b2/zh-Hans/frontend.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -194,21 +194,21 @@ const localazyMetadata: LocalazyMetadata = {
|
||||
file: "file.json",
|
||||
path: "",
|
||||
cdnFiles: {
|
||||
"cs": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/cs/file.json",
|
||||
"da": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/da/file.json",
|
||||
"de": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/de/file.json",
|
||||
"en": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/en/file.json",
|
||||
"et": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/et/file.json",
|
||||
"fi": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fi/file.json",
|
||||
"fr": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fr/file.json",
|
||||
"hu": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/hu/file.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nb-NO/file.json",
|
||||
"nl": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nl/file.json",
|
||||
"pt": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pt/file.json",
|
||||
"ru": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/ru/file.json",
|
||||
"sv": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/sv/file.json",
|
||||
"uk": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/uk/file.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a7686032324574572744739e0707/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/zh-Hans/file.json"
|
||||
"cs": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/cs/file.json",
|
||||
"da": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/da/file.json",
|
||||
"de": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/de/file.json",
|
||||
"en": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/en/file.json",
|
||||
"et": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/et/file.json",
|
||||
"fi": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fi/file.json",
|
||||
"fr": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/fr/file.json",
|
||||
"hu": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/hu/file.json",
|
||||
"nb_NO": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nb-NO/file.json",
|
||||
"nl": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/nl/file.json",
|
||||
"pt": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/pt/file.json",
|
||||
"ru": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/ru/file.json",
|
||||
"sv": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/sv/file.json",
|
||||
"uk": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/uk/file.json",
|
||||
"zh#Hans": "https://delivery.localazy.com/_a6763074727302097331c51429bd/_e0/5b69b0350dccfd47c245a5d41c1b9fdf6912cc6e/zh-Hans/file.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
},
|
||||
"nav": {
|
||||
"devices": "Устройства",
|
||||
"plan": "Plan",
|
||||
"plan": "Тарифный план",
|
||||
"profile": "Профиль",
|
||||
"sessions": "Сессии",
|
||||
"settings": "Настройки"
|
||||
@@ -302,9 +302,9 @@
|
||||
"name_for_platform": "{{name}} для {{platform}}",
|
||||
"scopes_label": "Области",
|
||||
"set_device_name": {
|
||||
"help": "Set a name that will help you identify this device.",
|
||||
"label": "Device name",
|
||||
"title": "Edit device name"
|
||||
"help": "Установите имя, которое поможет вам идентифицировать это устройство.",
|
||||
"label": "Имя устройства",
|
||||
"title": "Переименовать устройство"
|
||||
},
|
||||
"signed_in_date": "Вошёл <datetime/>",
|
||||
"signed_in_label": "Вошёл в систему",
|
||||
|
||||
@@ -28,7 +28,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
{{ captcha.head() }}
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout-container{% if consent_page %} consent{% endif %}">
|
||||
<div class="layout-container{% if consent_page is defined %} consent{% endif %}">
|
||||
{% block content %}{% endblock content %}
|
||||
{% include "components/footer.html" %}
|
||||
</div>
|
||||
|
||||
@@ -7,19 +7,19 @@ Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
<footer class="legal-footer">
|
||||
{%- if branding.policy_uri or branding.tos_uri -%}
|
||||
{%- if branding.policy_uri is not none or branding.tos_uri is not none -%}
|
||||
<nav>
|
||||
{%- if branding.policy_uri -%}
|
||||
{%- if branding.policy_uri is not none -%}
|
||||
<a href="{{ branding.policy_uri }}" referrerpolicy="no-referrer" title="{{ _('branding.privacy_policy.alt') }}" class="cpd-link" data-kind="primary">
|
||||
{{- _("branding.privacy_policy.link") -}}
|
||||
</a>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if branding.policy_uri and branding.tos_uri -%}
|
||||
{%- if branding.policy_uri is not none and branding.tos_uri is not none -%}
|
||||
<div class="separator" aria-hidden="true">•</div>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if branding.tos_uri -%}
|
||||
{%- if branding.tos_uri is not none -%}
|
||||
<a href="{{ branding.tos_uri }}" referrerpolicy="no-referrer" title="{{ _('branding.terms_and_conditions.alt') }}" class="cpd-link" data-kind="primary">
|
||||
{{- _("branding.terms_and_conditions.link") -}}
|
||||
</a>
|
||||
@@ -27,7 +27,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
</nav>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if branding.imprint -%}
|
||||
{%- if branding.imprint is not none -%}
|
||||
<p class="imprint">{{ branding.imprint }}</p>
|
||||
{%- endif -%}
|
||||
</footer>
|
||||
|
||||
@@ -15,7 +15,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form method="post" class="flex flex-col"{% if redirect_uri %} action="{{ redirect_uri }}"{% endif %}>
|
||||
<form method="post" class="flex flex-col"{% if redirect_uri is not none %} action="{{ redirect_uri }}"{% endif %}>
|
||||
{% for key, value in params|items %}
|
||||
<input type="hidden" name="{{ key }}" value="{{ value }}" />
|
||||
{% endfor %}
|
||||
|
||||
@@ -19,7 +19,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{% if current_session %}
|
||||
{% if current_session is not none %}
|
||||
<p class="cpd-text-body-md-regular">
|
||||
{{ _("mas.navbar.signed_in_as", username=current_session.user.username) }}
|
||||
</p>
|
||||
|
||||
@@ -49,7 +49,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autocomplete="new-password" required />
|
||||
{% endcall %}
|
||||
|
||||
{% if branding.tos_uri %}
|
||||
{% if branding.tos_uri is not none %}
|
||||
{% call(f) field.field(label=_("mas.register.terms_of_service", tos_uri=branding.tos_uri), name="accept_terms", form_state=form, inline=true, class="my-4") %}
|
||||
<div class="cpd-form-inline-field-control">
|
||||
<div class="cpd-checkbox-container">
|
||||
|
||||
@@ -26,7 +26,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
{% elif upstream_oauth_provider.human_name %}
|
||||
{% elif upstream_oauth_provider.human_name is not none %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.user_profile_solid() }}
|
||||
@@ -55,9 +55,9 @@ Please see LICENSE files in the repository root for full details.
|
||||
</header>
|
||||
{% endif %}
|
||||
|
||||
{% if upstream_oauth_provider.human_name %}
|
||||
{% if upstream_oauth_provider.human_name is not none %}
|
||||
<section class="upstream-oauth2-provider-account">
|
||||
{% if upstream_oauth_provider.brand_name %}
|
||||
{% if upstream_oauth_provider.brand_name is not none %}
|
||||
{{ logo(brand=upstream_oauth_provider.brand_name, class="brand") }}
|
||||
{% else %}
|
||||
{{ icon.user_profile() }}
|
||||
@@ -67,7 +67,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
<h3 class="provider">
|
||||
{{- _("mas.upstream_oauth2.register.provider_name", human_name=upstream_oauth_provider.human_name) -}}
|
||||
</h3>
|
||||
{% if upstream_oauth_link.human_account_name %}
|
||||
{% if upstream_oauth_link.human_account_name is not none %}
|
||||
<p class="account">
|
||||
{{- upstream_oauth_link.human_account_name -}}
|
||||
</p>
|
||||
@@ -147,7 +147,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" value="{{ imported_display_name }}" readonly />
|
||||
|
||||
<div class="cpd-form-message cpd-form-help-message">
|
||||
{% if upstream_oauth_provider.human_name %}
|
||||
{% if upstream_oauth_provider.human_name is not none %}
|
||||
{{- _("mas.upstream_oauth2.register.imported_from_upstream_with_name", human_name=upstream_oauth_provider.human_name) -}}
|
||||
{% else %}
|
||||
{{- _("mas.upstream_oauth2.register.imported_from_upstream") -}}
|
||||
@@ -175,7 +175,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if branding.tos_uri %}
|
||||
{% if branding.tos_uri is not none %}
|
||||
{% call(f) field.field(label=_("mas.register.terms_of_service", tos_uri=branding.tos_uri), name="accept_terms", form_state=form_state, inline=true, class="my-4") %}
|
||||
<div class="cpd-form-inline-field-control">
|
||||
<div class="cpd-checkbox-container">
|
||||
|
||||
@@ -101,6 +101,8 @@
|
||||
}
|
||||
},
|
||||
"device_display_name": {
|
||||
"client_on_device": "%(client_name)s на %(device_name)s",
|
||||
"name_for_platform": "%(name)s для %(platform)s",
|
||||
"unknown_device": "Неизвестное устройство"
|
||||
},
|
||||
"email_in_use": {
|
||||
@@ -208,6 +210,7 @@
|
||||
"register": {
|
||||
"call_to_login": "Уже есть аккаунт?",
|
||||
"continue_with_email": "Продолжить с адресом электронной почты",
|
||||
"continue_with_password": "Продолжить с паролем",
|
||||
"create_account": {
|
||||
"description": "Выберите имя пользователя, чтобы продолжить.",
|
||||
"heading": "Создать учётную запись"
|
||||
@@ -215,6 +218,11 @@
|
||||
"sign_in_instead": "Вместо этого войдите",
|
||||
"terms_of_service": "Я соглашаюсь с <a href=\"%s\" data-kind=\"primary\" class=\"cpd-link\">Правилами и положениями</a>"
|
||||
},
|
||||
"registration_token": {
|
||||
"description": "Введите токен регистрации, предоставленный администратором сервера.",
|
||||
"field": "Токен регистрации",
|
||||
"headline": "Токен регистрации"
|
||||
},
|
||||
"scope": {
|
||||
"edit_profile": "Редактировать профиль и контактную информацию",
|
||||
"manage_sessions": "Управлять устройствами и сеансами",
|
||||
@@ -230,6 +238,7 @@
|
||||
},
|
||||
"login_link": {
|
||||
"action": "Продолжить",
|
||||
"description": "Для этого имени пользователя (%(username)s) существует учетная запись, она будет связана с этой учетной записью.",
|
||||
"heading": "Связать с существующим аккаунтом"
|
||||
},
|
||||
"register": {
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
"continue_with_email": "使用邮件地址继续",
|
||||
"continue_with_password": "使用密码继续",
|
||||
"create_account": {
|
||||
"description": "请创建一个账户以开始使用:",
|
||||
"description": "选择一个用户名以继续。",
|
||||
"heading": "创建账户"
|
||||
},
|
||||
"sign_in_instead": "去登录",
|
||||
|
||||
Reference in New Issue
Block a user