Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Systemwide Default Language #992

Merged
merged 4 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions src/i18n/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import axios from 'axios';
import api from '../shared/api.json';

Vue.use(VueI18n);

async function getDefaultLanguage() {
try {
let url = `${api.BASE_URL}/${api.URL_CONFIG_PROPERTY}/public/general/default.language`;
let response = await axios.get(url);
return decodeURIComponent(response.data.propertyValue);
} catch (error) {
console.error('Error fetching default language:', error);
return '';
}
}

function loadLocaleMessages() {
const locales = require.context(
'./locales',
Expand Down Expand Up @@ -54,15 +67,20 @@ function matchLocale(requestedLocale) {
);
return 'en';
}

const i18n = new VueI18n({
locale: matchLocale(
locale: 'en',
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: localeMessages,
});

getDefaultLanguage().then((defaultLanguage) => {
const matchedLocale = matchLocale(
(localStorage && localStorage.getItem('Locale')) ||
defaultLanguage ||
navigator.language ||
navigator.userLanguage,
),
fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
messages: localeMessages,
);
i18n.locale = matchedLocale;
});

export default i18n;
3 changes: 3 additions & 0 deletions src/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Vorlage erstellen",
"create_user": "Benutzer erstellen",
"default": "Standard",
"default_language": "Standardsprache",
"default_language_desc": "Standardsprache, die für alle verwendet wird, wenn sie keine angegeben haben. \nWenn dies deaktiviert ist, wird die Sprache des Browsers verwendet.",
"default_language_enable": "Aktivieren Sie die Standardsprache",
"default_template_restored": "Standardvorlagen wiederhergestellt",
"defectdojo": "DefectDojo",
"delete_alert": "Alarm löschen",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Create Template",
"create_user": "Create User",
"default": "Default",
"default_language": "Default Language",
"default_language_desc": "Default language, which is used for everyone, when they didn't specify one. Langauge from Browser will be used, when this is disabled.",
"default_language_enable": "Enable Default language",
"default_template_restored": "Default templates restored",
"defectdojo": "DefectDojo",
"delete_alert": "Delete Alert",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Crear plantilla",
"create_user": "Crear usuario",
"default": "Por defecto",
"default_language": "Idioma predeterminado",
"default_language_desc": "Idioma predeterminado, que se usa para todos, cuando no especificaron uno. \nSe utilizará el idioma del navegador cuando esté deshabilitado.",
"default_language_enable": "Habilitar idioma predeterminado",
"default_template_restored": "Plantillas predeterminadas restauradas",
"defectdojo": "DefectoDojo",
"delete_alert": "Eliminar alerta",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Créer un modèle",
"create_user": "Créer un utilisateur",
"default": "Défaut",
"default_language": "Langue par défaut",
"default_language_desc": "Langue par défaut, qui est utilisée par tout le monde, lorsqu'ils n'en ont pas spécifié. \nLa langue du navigateur sera utilisée lorsqu'elle est désactivée.",
"default_language_enable": "Activer la langue par défaut",
"default_template_restored": "Modèles par défaut restaurés",
"defectdojo": "DefectDojo",
"delete_alert": "Supprimer l'alerte",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "टेम्पलेट बनाएं",
"create_user": "उपयोगकर्ता बनाइये",
"default": "गलती करना",
"default_language": "डिफ़ॉल्ट भाषा",
"default_language_desc": "डिफ़ॉल्ट भाषा, जिसका उपयोग सभी के लिए किया जाता है, जब उन्होंने किसी एक को निर्दिष्ट नहीं किया हो। \nइसे अक्षम करने पर ब्राउज़र से लैंग्वेज का उपयोग किया जाएगा।",
"default_language_enable": "डिफ़ॉल्ट भाषा सक्षम करें",
"default_template_restored": "डिफ़ॉल्ट टेम्पलेट्स पुनर्स्थापित किए गए",
"defectdojo": "डिफेक्टडोजो",
"delete_alert": "अलर्ट हटाएं",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Crea modello",
"create_user": "Creare un utente",
"default": "Predefinito",
"default_language": "Lingua predefinita",
"default_language_desc": "Lingua predefinita, utilizzata da tutti quando non ne è stata specificata una. \nQuando questa opzione è disabilitata, verrà utilizzata la lingua del browser.",
"default_language_enable": "Abilita la lingua predefinita",
"default_template_restored": "Modelli predefiniti ripristinati",
"defectdojo": "DifettoDojo",
"delete_alert": "Elimina avviso",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "テンプレートを作成",
"create_user": "ユーザーを作成",
"default": "デフォルト",
"default_language": "デフォルトの言語",
"default_language_desc": "デフォルトの言語。指定しなかった場合に全員に使用されます。\nこれを無効にすると、ブラウザの言語が使用されます。",
"default_language_enable": "デフォルト言語を有効にする",
"default_template_restored": "デフォルトのテンプレートが復元されました",
"defectdojo": "DefectDojo",
"delete_alert": "アラートを削除",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Utwórz szablon",
"create_user": "Stwórz użytkownika",
"default": "Domyślny",
"default_language": "Domyślny język",
"default_language_desc": "Domyślny język, którego używają wszyscy, jeśli go nie określili. \nJeśli ta opcja jest wyłączona, używany będzie język z przeglądarki.",
"default_language_enable": "Włącz język domyślny",
"default_template_restored": "Przywrócono domyślne szablony",
"defectdojo": "DefektDojo",
"delete_alert": "Usuń alert",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Criar modelo",
"create_user": "Criar usuário",
"default": "Padrão",
"default_language": "Idioma padrão",
"default_language_desc": "Idioma padrão, que é usado por todos, quando não especificam um. \nO idioma do navegador será usado quando estiver desabilitado.",
"default_language_enable": "Ativar idioma padrão",
"default_template_restored": "Modelos padrão restaurados",
"defectdojo": "DefectDojo",
"delete_alert": "Excluir alerta",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Criar modelo",
"create_user": "Criar utilizador",
"default": "Padrão",
"default_language": "Idioma padrão",
"default_language_desc": "Idioma padrão, que é usado por todos, quando não especificam um. \nO idioma do navegador será usado quando estiver desabilitado.",
"default_language_enable": "Ativar idioma padrão",
"default_template_restored": "Modelos padrão restaurados",
"defectdojo": "DefectDojo",
"delete_alert": "Excluir alerta",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Создать шаблон",
"create_user": "Создать пользователя",
"default": "По умолчанию",
"default_language": "Язык по умолчанию",
"default_language_desc": "Язык по умолчанию, который используется всеми, если они его не указали. \nЕсли эта опция отключена, будет использоваться язык из браузера.",
"default_language_enable": "Включить язык по умолчанию",
"default_template_restored": "Шаблоны по умолчанию восстановлены",
"defectdojo": "ДефектДодзё",
"delete_alert": "Удалить оповещение",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/uk-UA.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "Створити шаблон",
"create_user": "Створити користувача",
"default": "За замовчуванням",
"default_language": "Мова за замовчуванням",
"default_language_desc": "Мова за замовчуванням, яка використовується для всіх, якщо вони не вказали її. \nЯкщо цей параметр вимкнено, використовуватиметься мова з браузера.",
"default_language_enable": "Увімкнути мову за замовчуванням",
"default_template_restored": "Стандартні шаблони відновлено",
"defectdojo": "DefectDojo",
"delete_alert": "Видалити сповіщення",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"create_template": "创建模板",
"create_user": "创建用户",
"default": "默认",
"default_language": "默认语言",
"default_language_desc": "默认语言,当他们没有指定一种语言时,每个人都使用它。\n禁用时,将使用浏览器中的语言。",
"default_language_enable": "启用默认语言",
"default_template_restored": "恢复默认模板",
"defectdojo": "DefectDojo (一个开源的应用程序安全漏洞协调和管理平台)",
"delete_alert": "删除告警",
Expand Down
12 changes: 12 additions & 0 deletions src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import('@/views/administration/configuration/BomFormats');
const WelcomeMessage = () =>
import('@/views/administration/configuration/WelcomeMessage');
const DefaultLanguage = () =>
import('@/views/administration/configuration/DefaultLanguage');
const Email = () => import('@/views/administration/configuration/Email');
const Jira = () => import('@/views/administration/configuration/JiraConfig');
const InternalComponents = () =>
Expand Down Expand Up @@ -360,6 +362,16 @@
permission: 'SYSTEM_CONFIGURATION',
},
},
{
path: 'configuration/defaultLanguage',
component: DefaultLanguage,
meta: {
title: i18n.t('message.administration'),
i18n: 'message.administration',
sectionPath: '/admin',
permission: 'SYSTEM_CONFIGURATION',
},
},
{
path: 'configuration/email',
component: Email,
Expand Down Expand Up @@ -780,7 +792,7 @@
path: 'project',
props: (route) => ({ uuid: route.query.uuid }),
redirect: (to) => {
let { hash, params, query } = to;

Check failure on line 795 in src/router/index.js

View workflow job for this annotation

GitHub Actions / lint

'hash' is assigned a value but never used

Check failure on line 795 in src/router/index.js

View workflow job for this annotation

GitHub Actions / lint

'params' is assigned a value but never used
if (query.uuid) {
let uuid = query.uuid;
return { path: '/projects/' + uuid, query: null };
Expand All @@ -793,7 +805,7 @@
path: 'component',
props: (route) => ({ uuid: route.query.uuid }),
redirect: (to) => {
let { hash, params, query } = to;

Check failure on line 808 in src/router/index.js

View workflow job for this annotation

GitHub Actions / lint

'hash' is assigned a value but never used

Check failure on line 808 in src/router/index.js

View workflow job for this annotation

GitHub Actions / lint

'params' is assigned a value but never used
if (query.uuid) {
let uuid = query.uuid;
return { path: '/components/' + uuid, query: null };
Expand Down
5 changes: 5 additions & 0 deletions src/views/administration/AdminMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ export default {
name: this.$t('admin.bom_formats'),
route: 'configuration/bomFormats',
},
{
component: 'DefaultLanguage',
name: this.$t('admin.default_language'),
route: 'configuration/defaultLanguage',
},
{
component: 'Email',
name: this.$t('admin.email'),
Expand Down
2 changes: 2 additions & 0 deletions src/views/administration/Administration.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import AdminMenu from './AdminMenu';

// Configuration plugins
import BomFormats from './configuration/BomFormats';
import DefaultLanguage from './configuration/DefaultLanguage';
import Email from './configuration/Email';
import General from './configuration/General';
import InternalComponents from './configuration/InternalComponents';
Expand Down Expand Up @@ -75,6 +76,7 @@ export default {
General,
WelcomeMessage,
BomFormats,
DefaultLanguage,
Email,
Jira,
InternalComponents,
Expand Down
128 changes: 128 additions & 0 deletions src/views/administration/configuration/DefaultLanguage.vue
Gepardgame marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<template>
<b-card no-body :header="header">
<b-card-group>
<b-card-body>
<p>{{ $t('admin.default_language_desc') }}</p>
<b-form-group
:label="$t('admin.default_language')"
label-size="lg"
label-class="font-weight-bold pt-0 mb-2"
>
<div id="customToolbar">
<c-switch
id="default-language-enabled"
color="primary"
v-model="isDefaultLanguageEnabled"
label
v-bind="labelIcon"
/>{{ $t('admin.default_language_enable') }}
</div>
</b-form-group>
<b-input-group>
<b-input-group-prepend :title="this.$t('message.language')" is-text>
<span class="fa fa-language text-primary"></span>
</b-input-group-prepend>
<b-form-select
class="bg-widget"
v-model="defaultLanguage"
:disabled="!isDefaultLanguageEnabled"
>
<b-form-select-option
v-for="locale in $i18n.availableLocales"
:key="`locale-${locale}`"
:value="locale"
:title="$t(`language.${locale}`)"
>
<span class="mr-2">{{ localeToFlag(locale) }}</span>
{{ locale.toUpperCase() }}</b-form-select-option
>
</b-form-select>
</b-input-group>
</b-card-body>
</b-card-group>
<b-card-footer>
<b-button
:disabled="
this.isDefaultLanguageEnabled && this.defaultLanguage === ' '
"
variant="outline-primary"
class="px-4"
@click="saveChanges"
>
{{ $t('message.update') }}
</b-button>
</b-card-footer>
</b-card>
</template>

<script>
import axios from 'axios';
import LocalePicker from '@/views/components/LocalePicker.vue';
import { Switch as cSwitch } from '@coreui/vue';
export default {
props: {
header: String,
},
components: {
LocalePicker,
cSwitch,
},
data() {
return {
isDefaultLanguageEnabled: false,
defaultLanguage: 'en',
labelIcon: {
dataOn: '\u2713',
dataOff: '\u2715',
},
};
},
created() {
let url = `${this.$api.BASE_URL}/${this.$api.URL_CONFIG_PROPERTY}/public/general/default.language`;
axios.get(url).then((response) => {
this.defaultLanguage = decodeURIComponent(response.data.propertyValue);
this.isDefaultLanguageEnabled =
decodeURIComponent(response.data.propertyValue) !== ' ';
});
},
methods: {
localeToFlag: function (locale) {
// Largely taken from wojtekmaj/country-code-to-flag-emoji. Adopted to be able to deal with locale codes as inputs.
// https://github.com/wojtekmaj/country-code-to-flag-emoji/blob/ff0d3d2dd9680b6f860d85fc9e713e93e396adb7/src/index.ts

let countryCode = locale.split('-').pop().toUpperCase();
if (countryCode === 'EN') {
countryCode = 'US'; // Sorry Britain!
} else if (countryCode === 'HI') {
countryCode = 'IN';
} else if (countryCode === 'JA') {
countryCode = 'JP';
} else if (countryCode === 'ZH') {
countryCode = 'CN';
}

return Array.from(countryCode)
.map((letter) => letter.toLowerCase().charCodeAt(0) + 127365)
.map((charCode) => String.fromCodePoint(charCode))
.join('');
},
saveChanges() {
let url = `${this.$api.BASE_URL}/${this.$api.URL_CONFIG_PROPERTY}`;
axios
.post(url, {
groupName: 'general',
propertyName: 'default.language',
propertyValue: encodeURIComponent(
this.isDefaultLanguageEnabled ? this.defaultLanguage : ' ',
),
})
.then((response) => {
this.$toastr.s(this.$t('admin.configuration_saved'));
})
.catch((error) => {
this.$toastr.w(this.$t('condition.unsuccessful_action'));
});
},
},
};
</script>
Loading