Test rendering templates in all locales (#4497)

This commit is contained in:
Quentin Gliech authored and GitHub committed 2025-05-05 14:55:51 +02:00
commit 104e8f36f7
21 files changed
+146 -362

No files matched your search

+2 -2
View File
@@ -345,8 +345,8 @@ impl Translator {
/// Get a list of available locales.
#[must_use]
pub fn available_locales(&self) -> Vec<&DataLocale> {
self.translations.keys().collect()
pub fn available_locales(&self) -> Vec<DataLocale> {
self.translations.keys().cloned().collect()
}
/// Check if a locale is available.
+100 -44
View File
@@ -105,13 +105,17 @@ pub trait TemplateContext: Serialize {
///
/// This is then used to check for template validity in unit tests and in
/// the CLI (`cargo run -- templates check`)
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized;
}
impl TemplateContext for () {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -144,15 +148,19 @@ impl<T> std::ops::Deref for WithLanguage<T> {
}
impl<T: TemplateContext> TemplateContext for WithLanguage<T> {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
T::sample(now, rng)
.into_iter()
.map(|inner| WithLanguage {
lang: "en".into(),
inner,
locales
.iter()
.flat_map(|locale| {
T::sample(now, rng, locales)
.into_iter()
.map(move |inner| WithLanguage {
lang: locale.to_string(),
inner,
})
})
.collect()
}
@@ -168,11 +176,11 @@ pub struct WithCsrf<T> {
}
impl<T: TemplateContext> TemplateContext for WithCsrf<T> {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
T::sample(now, rng)
T::sample(now, rng, locales)
.into_iter()
.map(|inner| WithCsrf {
csrf_token: "fake_csrf_token".into(),
@@ -192,14 +200,14 @@ pub struct WithSession<T> {
}
impl<T: TemplateContext> TemplateContext for WithSession<T> {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
BrowserSession::samples(now, rng)
.into_iter()
.flat_map(|session| {
T::sample(now, rng)
T::sample(now, rng, locales)
.into_iter()
.map(move |inner| WithSession {
current_session: session.clone(),
@@ -220,7 +228,7 @@ pub struct WithOptionalSession<T> {
}
impl<T: TemplateContext> TemplateContext for WithOptionalSession<T> {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -229,7 +237,7 @@ impl<T: TemplateContext> TemplateContext for WithOptionalSession<T> {
.map(Some) // Wrap all samples in an Option
.chain(std::iter::once(None)) // Add the "None" option
.flat_map(|session| {
T::sample(now, rng)
T::sample(now, rng, locales)
.into_iter()
.map(move |inner| WithOptionalSession {
current_session: session.clone(),
@@ -257,7 +265,11 @@ impl Serialize for EmptyContext {
}
impl TemplateContext for EmptyContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -281,7 +293,11 @@ impl IndexContext {
}
impl TemplateContext for IndexContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -323,7 +339,11 @@ impl AppContext {
}
impl TemplateContext for AppContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -352,7 +372,11 @@ impl ApiDocContext {
}
impl TemplateContext for ApiDocContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -440,7 +464,11 @@ pub struct LoginContext {
}
impl TemplateContext for LoginContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -544,7 +572,11 @@ pub struct RegisterContext {
}
impl TemplateContext for RegisterContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -583,7 +615,11 @@ pub struct PasswordRegisterContext {
}
impl TemplateContext for PasswordRegisterContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -621,7 +657,7 @@ pub struct ConsentContext {
}
impl TemplateContext for ConsentContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -673,7 +709,7 @@ pub struct PolicyViolationContext {
}
impl TemplateContext for PolicyViolationContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -742,7 +778,7 @@ pub struct CompatSsoContext {
}
impl TemplateContext for CompatSsoContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -800,7 +836,7 @@ impl EmailRecoveryContext {
}
impl TemplateContext for EmailRecoveryContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -861,7 +897,7 @@ impl EmailVerificationContext {
}
impl TemplateContext for EmailVerificationContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -927,7 +963,7 @@ impl RegisterStepsVerifyEmailContext {
}
impl TemplateContext for RegisterStepsVerifyEmailContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -963,7 +999,11 @@ impl RegisterStepsEmailInUseContext {
}
impl TemplateContext for RegisterStepsEmailInUseContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -1014,7 +1054,11 @@ impl RegisterStepsDisplayNameContext {
}
impl TemplateContext for RegisterStepsDisplayNameContext {
fn sample(_now: chrono::DateTime<chrono::Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<chrono::Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -1061,7 +1105,11 @@ impl RecoveryStartContext {
}
impl TemplateContext for RecoveryStartContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -1099,7 +1147,7 @@ impl RecoveryProgressContext {
}
impl TemplateContext for RecoveryProgressContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1141,7 +1189,7 @@ impl RecoveryExpiredContext {
}
impl TemplateContext for RecoveryExpiredContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1202,7 +1250,7 @@ impl RecoveryFinishContext {
}
impl TemplateContext for RecoveryFinishContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1245,7 +1293,7 @@ impl UpstreamExistingLinkContext {
}
impl TemplateContext for UpstreamExistingLinkContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1277,7 +1325,7 @@ impl UpstreamSuggestLink {
}
impl TemplateContext for UpstreamSuggestLink {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1402,7 +1450,7 @@ impl UpstreamRegister {
}
impl TemplateContext for UpstreamRegister {
fn sample(now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, _rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1482,7 +1530,11 @@ impl DeviceLinkContext {
}
impl TemplateContext for DeviceLinkContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -1512,7 +1564,7 @@ impl DeviceConsentContext {
}
impl TemplateContext for DeviceConsentContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1553,7 +1605,7 @@ impl AccountInactiveContext {
}
impl TemplateContext for AccountInactiveContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1583,7 +1635,7 @@ impl DeviceNameContext {
}
impl TemplateContext for DeviceNameContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
@@ -1605,11 +1657,11 @@ pub struct FormPostContext<T> {
}
impl<T: TemplateContext> TemplateContext for FormPostContext<T> {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng, locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
let sample_params = T::sample(now, rng);
let sample_params = T::sample(now, rng, locales);
sample_params
.into_iter()
.map(|params| FormPostContext {
@@ -1678,7 +1730,11 @@ impl std::fmt::Display for ErrorContext {
}
impl TemplateContext for ErrorContext {
fn sample(_now: chrono::DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(
_now: chrono::DateTime<Utc>,
_rng: &mut impl Rng,
_locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
@@ -1768,7 +1824,7 @@ impl NotFoundContext {
}
impl TemplateContext for NotFoundContext {
fn sample(_now: DateTime<Utc>, _rng: &mut impl Rng) -> Vec<Self>
fn sample(_now: DateTime<Utc>, _rng: &mut impl Rng, _locales: &[DataLocale]) -> Vec<Self>
where
Self: Sized,
{
+3 -1
View File
@@ -6,6 +6,7 @@
use std::sync::Arc;
use mas_i18n::DataLocale;
use minijinja::{
Value,
value::{Enumerator, Object},
@@ -60,11 +61,12 @@ impl<T: TemplateContext> TemplateContext for WithCaptcha<T> {
fn sample(
now: chrono::DateTime<chrono::prelude::Utc>,
rng: &mut impl rand::prelude::Rng,
locales: &[DataLocale],
) -> Vec<Self>
where
Self: Sized,
{
let inner = T::sample(now, rng);
let inner = T::sample(now, rng, locales);
inner
.into_iter()
.map(|inner| Self::new(None, inner))
+8
View File
@@ -456,12 +456,20 @@ impl Templates {
check::render_recovery_disabled(self, now, rng)?;
check::render_form_post::<EmptyContext>(self, now, rng)?;
check::render_error(self, now, rng)?;
check::render_email_recovery_txt(self, now, rng)?;
check::render_email_recovery_html(self, now, rng)?;
check::render_email_recovery_subject(self, now, rng)?;
check::render_email_verification_txt(self, now, rng)?;
check::render_email_verification_html(self, now, rng)?;
check::render_email_verification_subject(self, now, rng)?;
check::render_upstream_oauth2_link_mismatch(self, now, rng)?;
check::render_upstream_oauth2_suggest_link(self, now, rng)?;
check::render_upstream_oauth2_do_register(self, now, rng)?;
check::render_device_link(self, now, rng)?;
check::render_device_consent(self, now, rng)?;
check::render_account_deactivated(self, now, rng)?;
check::render_account_locked(self, now, rng)?;
check::render_account_logged_out(self, now, rng)?;
check::render_device_name(self, now, rng)?;
Ok(())
}
+3 -2
View File
@@ -75,11 +75,12 @@ macro_rules! register_templates {
/// # Errors
///
/// Returns an error if the template fails to render with any of the sample.
pub fn $name
pub(crate) fn $name
$(< $( $lt $( : $clt $(+ $dlt )* + TemplateContext )? ),+ >)?
(templates: &Templates, now: chrono::DateTime<chrono::Utc>, rng: &mut impl rand::Rng)
-> anyhow::Result<()> {
let samples: Vec< $param > = TemplateContext::sample(now, rng);
let locales = templates.translator().available_locales();
let samples: Vec< $param > = TemplateContext::sample(now, rng, &locales);
let name = $template;
for sample in samples {
+1 -1
View File
@@ -300,7 +300,7 @@
"name_for_platform": "{{name}} für {{platform}}",
"scopes_label": "Berechtigungsumfang",
"set_device_name": {
"help": "Set a name that will help you identify this device.",
"help": "Geben Sie einen Namen ein, der Ihnen hilft, dieses Gerät zu identifizieren.",
"label": "Gerätename",
"title": "Gerätename bearbeiten"
},
+3 -3
View File
@@ -300,9 +300,9 @@
"name_for_platform": "{{name}} / {{platform}}",
"scopes_label": "Õigused",
"set_device_name": {
"help": "Set a name that will help you identify this device.",
"label": "Device name",
"title": "Edit device name"
"help": "Sisesta nimi, mis aitab sul hiljem seda seadet ära tunda.",
"label": "Seadme nimi",
"title": "Muuda seadme nime"
},
"signed_in_date": "Sisse logitud <datetime/>",
"signed_in_label": "Sisse logitud",
+3 -3
View File
@@ -300,9 +300,9 @@
"name_for_platform": "{{name}} {{platform}}:lle",
"scopes_label": "Vaikutusalue",
"set_device_name": {
"help": "Set a name that will help you identify this device.",
"label": "Device name",
"title": "Edit device name"
"help": "Aseta nimi, jonka avulla tunnistat tämän laitteen.",
"label": "Laitteen nimi",
"title": "Muokkaa laitteen nimeä"
},
"signed_in_date": "Kirjautunut sisään <datetime/>",
"signed_in_label": "Kirjautunut sisään",
+3 -3
View File
@@ -301,9 +301,9 @@
"name_for_platform": "{{name}} для {{platform}}",
"scopes_label": "Області застосування (Scopes)",
"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": "Вхід виконано",
+1 -1
View File
@@ -7,7 +7,7 @@
{
"file": "file.json",
"pattern": "translations/en.json",
"features": ["arb_metadata", "plural_object"]
"features": ["arb_metadata", "plural_object", "filter_untranslated"]
},
{
"file": "frontend.json",
-5
View File
@@ -100,11 +100,6 @@
"heading": "Přístup udělen"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "Pokud jste zapomněli přihlašovací údaje k účtu, můžete svůj účet obnovit. Můžete také začít znovu a použít jinou e-mailovou adresu.",
"title": "E-mailová adresa <span>%(email)s</span> se již používá"
-5
View File
@@ -100,11 +100,6 @@
"heading": "Adgang givet"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "Hvis du har glemt dine kontooplysninger, kan du gendanne din konto. Du kan også starte forfra og bruge en anden e-mail-adresse.",
"title": "E-mailadressen <span> %(email)s </span> er allerede i brug"
+3 -3
View File
@@ -101,9 +101,9 @@
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
"client_on_device": "%(client_name)s seadmes %(device_name)s",
"name_for_platform": "%(name)s platvormil %(platform)s",
"unknown_device": "Tundmatu seade"
},
"email_in_use": {
"description": "Kui sa oled unustanud oma konto kasutajanime ja/või salasõna, siis on sul võimalik taastada ligipääs oma kasutajakontole. Lisaks saad uue e-posti aadressi abil alustada nullist.",
+3 -3
View File
@@ -101,9 +101,9 @@
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
"client_on_device": "%(client_name)s %(device_name)s:lla",
"name_for_platform": "%(name)s %(platform)s:lle",
"unknown_device": "Tuntematon laite"
},
"email_in_use": {
"description": "Jos olet unohtanut tilisi tunnistetiedot, voit palauttaa tilisi. Voit myös aloittaa alusta ja käyttää toista sähköpostiosoitetta.",
+2 -2
View File
@@ -111,7 +111,7 @@
"copy_link": "Másolja a következő hivatkozást, és illessze be a böngészőbe egy új jelszó létrehozásához:",
"create_new_password": "Új jelszó létrehozása",
"fallback": "A gomb nem működik?",
"headline": "Jelszóvisszaállítást kért a(z) %(client_name)s fiókjához.",
"headline": "Jelszóvisszaállítást kért a(z) %(server_name)s fiókjához.",
"subject": "Fiókjelszó visszaállítása (%(mxid)s)",
"you_can_ignore": "Ha nem kért új jelszót, akkor figyelmen kívül hagyhatja ezt a levelet. A jelenlegi jelszava továbbra is működni fog."
},
@@ -262,4 +262,4 @@
"headline": "E-mail-cím ellenőrzése"
}
}
}
}
+5 -197
View File
@@ -6,14 +6,12 @@
"create_account": "Registreren",
"sign_in": "Inloggen",
"sign_out": "Uitloggen",
"skip": "Skip",
"start_over": "Opnieuw beginnen",
"submit": "Bevestigen"
},
"app": {
"human_name": "Matrix Authentication Service",
"name": "matrix-authentication-service",
"technical_description": "OpenID Connect discovery document: <a class=\"cpd-link\" data-kind=\"primary\" href=\"%(discovery_url)s\">%(discovery_url)s</a>"
"name": "matrix-authentication-service"
},
"branding": {
"privacy_policy": {
@@ -38,231 +36,41 @@
"unexpected": "Onverwachte fout"
},
"mas": {
"account": {
"deactivated": {
"description": "This account (<em>%(mxid)s</em>) has been deleted. If this is not expected, contact your server administrator.",
"heading": "Account deleted"
},
"locked": {
"description": "This account (<em>%(mxid)s</em>) has been locked. If this is not expected, contact your server administrator.",
"heading": "Account locked"
},
"logged_out": {
"description": "This session has been terminated. Sign out to be able to log back in",
"heading": "Session terminated"
}
},
"add_email": {
"description": "Enter an email address to recover your account in case you lose access to it.",
"heading": "Add an email address"
},
"back_to_homepage": "Go back to the homepage",
"captcha": {
"noscript": "This form is protected by a CAPTCHA and requires JavaScript to be enabled to submit it. Please enable JavaScript in your browser and reload this page."
},
"change_password": {
"change": "Wachtwoord wijzigen",
"confirm": "Bevestig wachtwoord",
"current": "Huidig wachtwoord",
"description": "This will change the password on your account.",
"heading": "Change my password",
"new": "New password"
},
"choose_display_name": {
"description": "This is the name other people will see. You can change this at any time.",
"headline": "Choose your display name"
},
"consent": {
"client_wants_access": "<span>%(client_name)s</span> at <span>%(redirect_uri)s</span> wants to access your account.",
"heading": "Allow access to your account?",
"make_sure_you_trust": "Make sure that you trust <span>%(client_name)s</span>.",
"this_will_allow": "This will allow <span>%(client_name)s</span> to:",
"you_may_be_sharing": "You may be sharing sensitive information with this site or app."
},
"device_card": {
"access_requested": "Access requested",
"device_code": "Code",
"generic_device": "Device",
"ip_address": "IP address"
},
"device_code_link": {
"description": "Link a device",
"headline": "Enter the code displayed on your device"
},
"device_consent": {
"another_device_access": "Another device wants to access your account.",
"denied": {
"description": "You denied access to %(client_name)s. You can close this window.",
"heading": "Access denied"
},
"granted": {
"description": "You granted access to %(client_name)s. You can close this window.",
"heading": "Access granted"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "If you have forgotten your account credentials, you can recover your account. You can also start over and use a different email address.",
"title": "The email address <span>%(email)s</span> is already in use"
},
"emails": {
"greeting": "Hello %(username)s,",
"recovery": {
"click_button": "Click on the button below to create a new password:",
"copy_link": "Copy the following link and paste it into a browser to create a new password:",
"create_new_password": "Create new password",
"fallback": "The button doesn't work for you?",
"headline": "You requested a password reset for your %(server_name)s account.",
"subject": "Reset your account password (%(mxid)s)",
"you_can_ignore": "If you didn't ask for a new password, you can ignore this email. Your current password will continue to work."
},
"verify": {
"body_html": "Your verification code to confirm this email address is: <strong>%(code)s</strong>",
"body_text": "Your verification code to confirm this email address is: %(code)s",
"subject": "Your email verification code is: %(code)s"
}
"current": "Huidig wachtwoord"
},
"errors": {
"captcha": "CAPTCHA verification failed, please try again",
"denied_policy": "Denied by policy: %(policy)s",
"email_banned": "Email is banned by the server policy",
"email_domain_banned": "Email domain is banned by the server policy",
"email_domain_not_allowed": "Email domain is not allowed by the server policy",
"email_not_allowed": "Email is not allowed by the server policy",
"field_required": "This field is required",
"invalid_credentials": "Ongeldige gegevens",
"password_mismatch": "Password fields don't match",
"rate_limit_exceeded": "You've made too many requests in a short period. Please wait a few minutes and try again.",
"username_all_numeric": "Username cannot consist solely of numbers",
"username_banned": "Username is banned by the server policy",
"username_invalid_chars": "Username contains invalid characters. Use lowercase letters, numbers, dashes and underscores only.",
"username_not_allowed": "Username is not allowed by the server policy",
"username_taken": "This username is already taken",
"username_too_long": "Username is too long",
"username_too_short": "Username is too short"
"invalid_credentials": "Ongeldige gegevens"
},
"login": {
"call_to_register": "Don't have an account yet?",
"continue_with_provider": "Doorgaan met %(provider)s",
"description": "Please sign in to continue:",
"forgot_password": "Forgot password?",
"headline": "Inloggen",
"link": {
"description": "Linking your <span class=\"break-keep text-links\">%(provider)s</span> account",
"headline": "Sign in to link"
},
"no_login_methods": "No login methods available.",
"separator": "Of",
"username_or_email": "Username or Email"
"separator": "Of"
},
"navbar": {
"my_account": "Mijn account",
"register": "Create an account",
"signed_in_as": "Signed in as <span class=\"font-semibold\">%(username)s</span>."
"my_account": "Mijn account"
},
"not_found": {
"description": "The page you were looking for doesn't exist or has been moved",
"heading": "Page not found"
},
"not_you": "Not %(username)s?",
"or_separator": "Of",
"policy_violation": {
"description": "This might be because of the client which authored the request, the currently logged in user, or the request itself.",
"heading": "The authorization request was denied the policy enforced by this service",
"logged_as": "Logged as <span class=\"font-semibold\">%(username)s</span>"
},
"recovery": {
"consumed": {
"description": "To create a new password, start over and select “Forgot password”.",
"heading": "The link to reset your password has already been used"
},
"disabled": {
"description": "If you have lost your credentials, please contact the administrator to recover your account.",
"heading": "Account recovery is disabled"
},
"expired": {
"description": "Request a new email that will be sent to: <span>%(email)s</span>.",
"heading": "The link to reset your password has expired",
"resend_email": "Resend email"
},
"finish": {
"confirm": "Enter new password again",
"description": "Choose a new password for your account.",
"heading": "Reset your password",
"new": "New password",
"save_and_continue": "Save and continue"
},
"progress": {
"change_email": "Try a different email",
"description": "We sent an email with a link to reset your password if there's an account using <span>%(email)s</span>.",
"heading": "Check your email",
"resend_email": "Resend email"
},
"start": {
"description": "An email will be sent with a link to reset your password.",
"heading": "Enter your email to continue"
}
},
"register": {
"call_to_login": "Already have an account?",
"continue_with_email": "Continue with email address",
"create_account": {
"description": "Choose a username to continue.",
"heading": "Create an account"
},
"sign_in_instead": "Sign in instead",
"terms_of_service": "I agree to the <a href=\"%s\" data-kind=\"primary\" class=\"cpd-link\">Terms and Conditions</a>"
},
"scope": {
"edit_profile": "Edit your profile and contact details",
"manage_sessions": "Manage your devices and sessions",
"mas_admin": "Administer any user on the matrix-authentication-service",
"send_messages": "Send new messages on your behalf",
"synapse_admin": "Administer the Synapse homeserver",
"view_messages": "View your existing messages and data",
"view_profile": "See your profile info and contact details"
},
"upstream_oauth2": {
"link_mismatch": {
"heading": "This upstream account is already linked to another account."
},
"register": {
"choose_username": {
"description": "This cannot be changed later.",
"heading": "Kies uw gebruikersnaam"
},
"create_account": "Nieuw account aanmaken",
"enforced_by_policy": "Enforced by server policy",
"forced_display_name": "Will use the following display name",
"forced_email": "De volgende e-mailadres zal worden gebruikt",
"forced_localpart": "De volgende gebruikersnaam zal worden gebruikt",
"import_data": {
"description": "Confirm the information that will be linked to your new %(server_name)s account.",
"heading": "Importeer uw data"
},
"imported_from_upstream": "Imported from your upstream account",
"imported_from_upstream_with_name": "Imported from your %(human_name)s account",
"link_existing": "Link to an existing account",
"provider_name": "%(human_name)s account",
"signup_with_upstream": {
"heading": "Continue signing up with your %(human_name)s account"
},
"suggested_display_name": "Weergavenaam importeren",
"suggested_email": "E-mailadres importeren",
"use": "Gebruiken"
},
"suggest_link": {
"action": "Link",
"heading": "Link to your existing account"
}
},
"verify_email": {
"6_digit_code": "6-cijferige code",
"code": "Code",
"description": "Voer de 6-cijferige code in die is verzonden naar: <em>%(email)s</em>",
"headline": "Verifieer uw e-mailadres"
}
-5
View File
@@ -100,11 +100,6 @@
"heading": "Acesso concedido"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "Se se esqueceu das suas credenciais de conta, pode recuperar a sua conta. Também pode começar de novo e utilizar um endereço de correio eletrónico diferente.",
"title": "O endereço de correio eletrónico <span>%(email)s</span> já está a ser utilizado"
-5
View File
@@ -100,11 +100,6 @@
"heading": "Доступ предоставлен"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "Если вы забыли учетные данные, вы можете восстановить свою учётную запись. Вы также можете начать сначала и использовать другой адрес электронной почты.",
"title": "Адрес электронной почты <span>%(email)s</span> уже используется"
+1 -26
View File
@@ -38,20 +38,6 @@
"unexpected": "Oväntat fel"
},
"mas": {
"account": {
"deactivated": {
"description": "This account (<em>%(mxid)s</em>) has been deleted. If this is not expected, contact your server administrator.",
"heading": "Account deleted"
},
"locked": {
"description": "This account (<em>%(mxid)s</em>) has been locked. If this is not expected, contact your server administrator.",
"heading": "Account locked"
},
"logged_out": {
"description": "This session has been terminated. Sign out to be able to log back in",
"heading": "Session terminated"
}
},
"add_email": {
"description": "Ange en e-postadress för att återställa ditt konto om du förlorar åtkomsten till det.",
"heading": "Lägg till en e-postadress"
@@ -100,11 +86,6 @@
"heading": "Åtkomst beviljad"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "Om du har glömt dina kontouppgifter kan du återställa ditt konto. Du kan också börja om och använda en annan e-postadress.",
"title": "E-postadressen <span>%(email)s</span> är redan i bruk"
@@ -115,7 +96,6 @@
"click_button": "Klicka på knappen nedan för att skapa ett nytt lösenord:",
"copy_link": "Kopiera följande länk och klistra in den i en webbläsare för att skapa ett nytt lösenord:",
"create_new_password": "Skapa nytt lösenord",
"fallback": "The button doesn't work for you?",
"headline": "Du begärde en lösenordsåterställning för ditt %(server_name)s konto.",
"subject": "Återställ ditt kontolösenord (%(mxid)s)",
"you_can_ignore": "Om du inte har bett om ett nytt lösenord kan du ignorera detta e-postmeddelande. Ditt nuvarande lösenord kommer att fortsätta att fungera."
@@ -129,18 +109,14 @@
"errors": {
"captcha": "CAPTCHA-verifiering misslyckades, försök igen",
"denied_policy": "Nekad av policy: %(policy)s",
"email_banned": "Email is banned by the server policy",
"email_domain_banned": "E-postdomänen är förbjuden av serverpolicyn",
"email_domain_not_allowed": "E-postdomänen är inte tillåten enligt serverpolicyn",
"email_not_allowed": "Email is not allowed by the server policy",
"field_required": "Detta fält är obligatoriskt",
"invalid_credentials": "Ogiltiga autentiseringsuppgifter",
"password_mismatch": "Lösenordsfälten matchar inte",
"rate_limit_exceeded": "Du har gjort för många förfrågningar under en kort period. Vänta några minuter och försök igen.",
"username_all_numeric": "Användarnamn kan inte enbart bestå av siffror",
"username_banned": "Username is banned by the server policy",
"username_invalid_chars": "Användarnamnet innehåller ogiltiga tecken. Använd endast små bokstäver, siffror, streck och understreck.",
"username_not_allowed": "Username is not allowed by the server policy",
"username_taken": "Detta användarnamn är redan upptaget",
"username_too_long": "Användarnamnet är för långt",
"username_too_short": "Användarnamnet är för kort"
@@ -156,8 +132,7 @@
"headline": "Logga in för att länka"
},
"no_login_methods": "Inga inloggningsmetoder tillgängliga.",
"separator": "eller",
"username_or_email": "Username or Email"
"separator": "eller"
},
"navbar": {
"my_account": "Mitt konto",
+3 -3
View File
@@ -101,9 +101,9 @@
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
"client_on_device": "%(client_name)s на %(device_name)s",
"name_for_platform": "%(name)s для %(platform)s",
"unknown_device": "Невідомий пристрій"
},
"email_in_use": {
"description": "Якщо ви забули облікові дані облікового запису, ви можете відновити свій обліковий запис. Ви також можете почати спочатку і використовувати іншу адресу електронної пошти.",
+2 -48
View File
@@ -6,7 +6,6 @@
"create_account": "创建账户",
"sign_in": "登录",
"sign_out": "注销",
"skip": "Skip",
"start_over": "重新开始",
"submit": "提交"
},
@@ -38,20 +37,6 @@
"unexpected": "意外错误"
},
"mas": {
"account": {
"deactivated": {
"description": "This account (<em>%(mxid)s</em>) has been deleted. If this is not expected, contact your server administrator.",
"heading": "Account deleted"
},
"locked": {
"description": "This account (<em>%(mxid)s</em>) has been locked. If this is not expected, contact your server administrator.",
"heading": "Account locked"
},
"logged_out": {
"description": "This session has been terminated. Sign out to be able to log back in",
"heading": "Session terminated"
}
},
"add_email": {
"description": "输入电子邮件地址,以便在失去访问权限时恢复账户。",
"heading": "添加电子邮件地址"
@@ -68,10 +53,6 @@
"heading": "更改我的密码",
"new": "新密码"
},
"choose_display_name": {
"description": "This is the name other people will see. You can change this at any time.",
"headline": "Choose your display name"
},
"consent": {
"client_wants_access": "<span>%(client_name)s</span> 在 <span>%(redirect_uri)s</span> 希望访问您的账户。",
"heading": "允许访问您的账户?",
@@ -100,22 +81,12 @@
"heading": "已授予访问权限"
}
},
"device_display_name": {
"client_on_device": "%(client_name)s on %(device_name)s",
"name_for_platform": "%(name)s for %(platform)s",
"unknown_device": "Unknown device"
},
"email_in_use": {
"description": "If you have forgotten your account credentials, you can recover your account. You can also start over and use a different email address.",
"title": "The email address <span>%(email)s</span> is already in use"
},
"emails": {
"greeting": "%(username)s 你好,",
"recovery": {
"click_button": "点击下面的按钮创建新密码:",
"copy_link": "复制以下链接并粘贴到浏览器中以创建新密码:",
"create_new_password": "创建新密码",
"fallback": "The button doesn't work for you?",
"headline": "您请求重置您在 %(server_name)s 的账户密码。",
"subject": "重置账户密码 (%(mxid)s)",
"you_can_ignore": "如果您没有请求重置密码,可以忽略此邮件。您当前的密码仍然有效。"
@@ -129,21 +100,11 @@
"errors": {
"captcha": "验证码验证失败,请重试",
"denied_policy": "被该策略拒绝:%(policy)s",
"email_banned": "Email is banned by the server policy",
"email_domain_banned": "Email domain is banned by the server policy",
"email_domain_not_allowed": "Email domain is not allowed by the server policy",
"email_not_allowed": "Email is not allowed by the server policy",
"field_required": "此字段为必填项",
"invalid_credentials": "无效的凭据",
"password_mismatch": "密码字段不匹配",
"rate_limit_exceeded": "您在短时间内发出了过多请求。请等待几分钟后重试。",
"username_all_numeric": "Username cannot consist solely of numbers",
"username_banned": "Username is banned by the server policy",
"username_invalid_chars": "Username contains invalid characters. Use lowercase letters, numbers, dashes and underscores only.",
"username_not_allowed": "Username is not allowed by the server policy",
"username_taken": "此用户名已被使用",
"username_too_long": "Username is too long",
"username_too_short": "Username is too short"
"username_taken": "此用户名已被使用"
},
"login": {
"call_to_register": "还没有账户?",
@@ -156,8 +117,7 @@
"headline": "登录以链接"
},
"no_login_methods": "没有可用的登录途径。",
"separator": "或",
"username_or_email": "Username or Email"
"separator": "或"
},
"navbar": {
"my_account": "我的账户",
@@ -209,7 +169,6 @@
},
"register": {
"call_to_login": "已有账户?",
"continue_with_email": "Continue with email address",
"create_account": {
"description": "请创建一个账户以开始使用:",
"heading": "创建账户"
@@ -245,12 +204,7 @@
"heading": "导入数据"
},
"imported_from_upstream": "从上游账户导入",
"imported_from_upstream_with_name": "Imported from your %(human_name)s account",
"link_existing": "链接到现有账户",
"provider_name": "%(human_name)s account",
"signup_with_upstream": {
"heading": "Continue signing up with your %(human_name)s account"
},
"suggested_display_name": "导入显示名称",
"suggested_email": "导入电子邮件地址",
"use": "使用"