Merge 934874a94e into 9169a647cb
This commit is contained in:
commit
96670211ad
@ -0,0 +1,11 @@
|
|||||||
|
exports.up = async function (knex) {
|
||||||
|
await knex.schema.alterTable("status_page", function (table) {
|
||||||
|
table.string("language", 20);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.alterTable("status_page", function (table) {
|
||||||
|
table.dropColumn("language");
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -450,6 +450,7 @@ class StatusPage extends BeanModel {
|
|||||||
showCertificateExpiry: !!this.show_certificate_expiry,
|
showCertificateExpiry: !!this.show_certificate_expiry,
|
||||||
showOnlyLastHeartbeat: !!this.show_only_last_heartbeat,
|
showOnlyLastHeartbeat: !!this.show_only_last_heartbeat,
|
||||||
rssTitle: this.rss_title,
|
rssTitle: this.rss_title,
|
||||||
|
language: this.language,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,6 +478,7 @@ class StatusPage extends BeanModel {
|
|||||||
showCertificateExpiry: !!this.show_certificate_expiry,
|
showCertificateExpiry: !!this.show_certificate_expiry,
|
||||||
showOnlyLastHeartbeat: !!this.show_only_last_heartbeat,
|
showOnlyLastHeartbeat: !!this.show_only_last_heartbeat,
|
||||||
rssTitle: this.rss_title,
|
rssTitle: this.rss_title,
|
||||||
|
language: this.language,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -339,6 +339,11 @@ module.exports.statusPageSocketHandler = (socket) => {
|
|||||||
statusPage.analytics_id = config.analyticsId;
|
statusPage.analytics_id = config.analyticsId;
|
||||||
statusPage.analytics_script_url = config.analyticsScriptUrl;
|
statusPage.analytics_script_url = config.analyticsScriptUrl;
|
||||||
statusPage.analytics_type = config.analyticsType;
|
statusPage.analytics_type = config.analyticsType;
|
||||||
|
if (typeof config.language === "string" && config.language.trim() !== "") {
|
||||||
|
statusPage.language = config.language.trim();
|
||||||
|
} else {
|
||||||
|
statusPage.language = null;
|
||||||
|
}
|
||||||
|
|
||||||
await R.store(statusPage);
|
await R.store(statusPage);
|
||||||
|
|
||||||
|
|||||||
@ -95,8 +95,8 @@ export function currentLocale() {
|
|||||||
return "en";
|
return "en";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const localeDirection = () => {
|
export const localeDirection = (locale = currentLocale()) => {
|
||||||
return rtlLangs.includes(currentLocale()) ? "rtl" : "ltr";
|
return rtlLangs.includes(locale) ? "rtl" : "ltr";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const i18n = createI18n({
|
export const i18n = createI18n({
|
||||||
|
|||||||
@ -425,6 +425,9 @@
|
|||||||
"Footer Text": "Footer Text",
|
"Footer Text": "Footer Text",
|
||||||
"RSS Title": "RSS Title",
|
"RSS Title": "RSS Title",
|
||||||
"Leave blank to use status page title": "Leave blank to use status page title",
|
"Leave blank to use status page title": "Leave blank to use status page title",
|
||||||
|
"Status Page Language": "Status Page Language",
|
||||||
|
"Use browser language": "Use browser language",
|
||||||
|
"statusPageLanguageDescription": "Set the display language for anonymous visitors to this status page",
|
||||||
"Refresh Interval": "Refresh Interval",
|
"Refresh Interval": "Refresh Interval",
|
||||||
"Refresh Interval Description": "The status page will do a full site refresh every {0} seconds",
|
"Refresh Interval Description": "The status page will do a full site refresh every {0} seconds",
|
||||||
"Show Powered By": "Show Powered By",
|
"Show Powered By": "Show Powered By",
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
language: currentLocale(),
|
language: currentLocale(),
|
||||||
|
persistLanguage: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -17,22 +18,40 @@ export default {
|
|||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
async language(lang) {
|
async language(lang) {
|
||||||
await this.changeLang(lang);
|
await this.changeLang(lang, {
|
||||||
|
persist: this.persistLanguage,
|
||||||
|
});
|
||||||
|
this.persistLanguage = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
/**
|
||||||
|
* Set the application language
|
||||||
|
* @param {string} lang Language code to switch to
|
||||||
|
* @param {{ persist?: boolean }} options Options for language change
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
setLanguage(lang, options = {}) {
|
||||||
|
this.persistLanguage = options.persist !== false;
|
||||||
|
this.language = lang;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the application language
|
* Change the application language
|
||||||
* @param {string} lang Language code to switch to
|
* @param {string} lang Language code to switch to
|
||||||
|
* @param {{ persist?: boolean }} options Options for language change
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async changeLang(lang) {
|
async changeLang(lang, options = {}) {
|
||||||
|
const persist = options.persist !== false;
|
||||||
let message = (await langModules["../lang/" + lang + ".json"]()).default;
|
let message = (await langModules["../lang/" + lang + ".json"]()).default;
|
||||||
this.$i18n.setLocaleMessage(lang, message);
|
this.$i18n.setLocaleMessage(lang, message);
|
||||||
this.$i18n.locale = lang;
|
this.$i18n.locale = lang;
|
||||||
localStorage.locale = lang;
|
if (persist) {
|
||||||
setPageLocale();
|
localStorage.locale = lang;
|
||||||
|
}
|
||||||
|
setPageLocale(lang);
|
||||||
timeDurationFormatter.updateLocale(lang);
|
timeDurationFormatter.updateLocale(lang);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -201,6 +201,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Status Page Language -->
|
||||||
|
<div class="my-3">
|
||||||
|
<label for="status-page-language" class="form-label">{{ $t("Status Page Language") }}</label>
|
||||||
|
<select
|
||||||
|
id="status-page-language"
|
||||||
|
v-model="config.language"
|
||||||
|
class="form-select"
|
||||||
|
data-testid="language-select"
|
||||||
|
>
|
||||||
|
<option :value="null">{{ $t("Use browser language") }}</option>
|
||||||
|
<option v-for="lang in $i18n.availableLocales" :key="lang" :value="lang">
|
||||||
|
{{ $i18n.messages[lang].languageName }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<div class="form-text">
|
||||||
|
{{ $t("statusPageLanguageDescription") }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Custom CSS -->
|
<!-- Custom CSS -->
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<div class="mb-1">{{ $t("Custom CSS") }}</div>
|
<div class="mb-1">{{ $t("Custom CSS") }}</div>
|
||||||
@ -905,6 +924,10 @@ export default {
|
|||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
this.config = res.config;
|
this.config = res.config;
|
||||||
|
|
||||||
|
if (!("language" in this.config)) {
|
||||||
|
this.config.language = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.config.customCSS) {
|
if (!this.config.customCSS) {
|
||||||
this.config.customCSS = "body {\n" + " \n" + "}\n";
|
this.config.customCSS = "body {\n" + " \n" + "}\n";
|
||||||
}
|
}
|
||||||
@ -990,6 +1013,27 @@ export default {
|
|||||||
this.config.domainNameList = [];
|
this.config.domainNameList = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!("language" in this.config)) {
|
||||||
|
this.config.language = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.config.icon) {
|
||||||
|
this.imgDataUrl = this.config.icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply configured language if the visitor hasn't set their own preference
|
||||||
|
if (this.config.language && !localStorage.locale) {
|
||||||
|
this.$root.setLanguage(this.config.language, { persist: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.incident = res.data.incident;
|
||||||
|
this.maintenanceList = res.data.maintenanceList;
|
||||||
|
this.$root.publicGroupList = res.data.publicGroupList;
|
||||||
|
|
||||||
|
if (!this.config.domainNameList) {
|
||||||
|
this.config.domainNameList = [];
|
||||||
|
}
|
||||||
|
|
||||||
if (this.config.icon) {
|
if (this.config.icon) {
|
||||||
this.imgDataUrl = this.config.icon;
|
this.imgDataUrl = this.config.icon;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,12 +62,13 @@ export function timezoneList() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the locale of the HTML page
|
* Set the locale of the HTML page
|
||||||
|
* @param {string} locale The locale to use
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function setPageLocale() {
|
export function setPageLocale(locale = currentLocale()) {
|
||||||
const html = document.documentElement;
|
const html = document.documentElement;
|
||||||
html.setAttribute("lang", currentLocale());
|
html.setAttribute("lang", locale);
|
||||||
html.setAttribute("dir", localeDirection());
|
html.setAttribute("dir", localeDirection(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user